From 90ee2d6a45e360756a6d65e219f0bdaba6c4a3a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=91=ED=98=84?= Date: Tue, 5 Sep 2023 10:43:19 +0900 Subject: [PATCH 01/15] =?UTF-8?q?=20[Feat]=ED=97=A4=EB=8D=94=20develop=20?= =?UTF-8?q?=EB=A1=9C=EA=B3=A0=20=ED=81=B4=EB=A6=AD=20=EC=8B=9C=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=ED=8E=98=EC=9D=B4=EC=A7=80=EB=A1=9C=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=20=EC=A3=BC=EC=84=9D=20=EC=B6=94=EA=B0=80=20Issues#2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/Headers/LogoutHeader.tsx | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/client/src/components/Headers/LogoutHeader.tsx b/client/src/components/Headers/LogoutHeader.tsx index 484475fe..9451a272 100644 --- a/client/src/components/Headers/LogoutHeader.tsx +++ b/client/src/components/Headers/LogoutHeader.tsx @@ -1,20 +1,25 @@ import React, { useState } from "react"; import styled from "styled-components"; import StockHolmLogo from "../../asset/images/StockHolmLogo.png"; +import { useNavigate } from "react-router-dom"; // 라우터의 히스토리를 사용하기 위해 가져옴 const LogoutHeader: React.FC = ({ onLoginClick }) => { - const [searchValue, setSearchValue] = useState(""); + const [searchValue, setSearchValue] = useState(""); // 검색 값 상태 관리 + const navigate = useNavigate(); // 라우터 히스토리 훅 사용 + // 검색 입력 변경 핸들러 const handleSearchChange = (event: React.ChangeEvent) => { setSearchValue(event.target.value); }; - const loginText = "로그인"; + const loginText = "로그인"; // 로그인 버튼 텍스트 + // 로고 클릭 핸들러 const handleLogoClick = () => { - console.log("Logo clicked"); + navigate("/"); // 메인 페이지로 이동 }; + // 컴포넌트 렌더링 return ( @@ -26,13 +31,14 @@ const LogoutHeader: React.FC = ({ onLoginClick }) => { ); }; +// 스타일드 컴포넌트 정의 const HeaderContainer = styled.div` display: flex; justify-content: space-between; align-items: center; padding: 1rem 2rem; background-color: #fff; - border-bottom: 1px solid #2f4f4f; // 다크 슬레이트 그레이 줄 + border-bottom: 1px solid #2f4f4f; width: 100%; height: 51px; `; @@ -42,7 +48,6 @@ const LogoButton = styled.button` border: none; cursor: pointer; padding: 0; - &:focus { outline: none; } @@ -64,18 +69,19 @@ const SearchBar = styled.input.attrs({ `; const LoginButton = styled.button` - background-color: #fff; // 흰색 배경 - color: #2f4f4f; // 글자색 - border: 1px solid #2f4f4f; // 회색 테두리 + background-color: #fff; + color: #2f4f4f; + border: 1px solid #2f4f4f; padding: 0.5rem 1rem; - border-radius: 5px; // 5px 둥글게 + border-radius: 5px; cursor: pointer; transition: background-color 0.3s; - &:hover { - background-color: #f2f2f2; // 호버 시 약간 어두운 흰색으로 변경 + background-color: #f2f2f2; } `; + +// 프롭스 타입 정의 interface LogoutHeaderProps { onLoginClick: () => void; } From 4b137c963ff251725c476c8cc64f411ee674fa2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=91=ED=98=84?= Date: Tue, 5 Sep 2023 10:58:31 +0900 Subject: [PATCH 02/15] =?UTF-8?q?[Feat]=ED=97=A4=EB=8D=94=20develop#2=20?= =?UTF-8?q?=EB=A1=9C=EA=B3=A0=20=ED=81=B4=EB=A6=AD=20=EC=8B=9C=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=ED=8E=98=EC=9D=B4=EC=A7=80=EB=A1=9C=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=20=EC=A3=BC=EC=84=9D=20=EC=B6=94=EA=B0=80=20Issues#3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/components/Headers/LoginHeader.tsx | 39 ++++++++++++------- .../src/components/Headers/LogoutHeader.tsx | 8 ++-- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/client/src/components/Headers/LoginHeader.tsx b/client/src/components/Headers/LoginHeader.tsx index 4ddd3947..de6cadd6 100644 --- a/client/src/components/Headers/LoginHeader.tsx +++ b/client/src/components/Headers/LoginHeader.tsx @@ -3,18 +3,23 @@ import styled from 'styled-components'; import StockHolmLogo from "../../asset/images/StockHolmLogo.png"; import SampleProfile from "../../asset/images/ProfileSample.png"; import AlarmImage from "../../asset/images/alarm.png"; +import { useNavigate } from "react-router-dom"; // 페이지 이동을 위한 훅 가져오기 +// 로그인 상태일 때의 헤더 컴포넌트 const LoginHeader: React.FC = ({ onLogoutClick }) => { - const [searchValue, setSearchValue] = useState(''); + const [searchValue, setSearchValue] = useState(''); // 검색어 상태 + const navigate = useNavigate(); // 페이지 이동 함수 + // 검색어 입력 처리 함수 const handleSearchChange = (event: React.ChangeEvent) => { setSearchValue(event.target.value); }; const logoutText = "로그아웃"; + // 로고 클릭 처리 함수 const handleLogoClick = () => { - console.log("Logo clicked"); + navigate("/"); // 메인 페이지로 이동 }; return ( @@ -25,12 +30,12 @@ const LoginHeader: React.FC = ({ onLogoutClick }) => { - Notification + Notification // 알림 이미지 - + // 프로필 이미지 - {logoutText} {/* 로그아웃 버튼 클릭 시 onLogoutClick 실행 */} + {logoutText} // 로그아웃 버튼 ); @@ -38,37 +43,41 @@ const LoginHeader: React.FC = ({ onLogoutClick }) => { export default LoginHeader; +// 로그아웃 클릭 이벤트 타입 정의 interface LoginHeaderProps { - onLogoutClick: () => void; // 로그아웃 클릭 핸들러 타입 정의 + onLogoutClick: () => void; } +// 헤더 컨테이너 스타일 const HeaderContainer = styled.div` display: flex; justify-content: space-between; align-items: center; - padding: 1rem 2rem ; + padding: 1rem 2rem; background-color: #fff; border-bottom: 1px solid #2F4F4F; width: 100%; height: 51px; `; +// 로고 버튼 스타일 const LogoButton = styled.button` background: transparent; border: none; cursor: pointer; padding: 0; - &:focus { outline: none; } `; +// 로고 이미지 스타일 const LogoImage = styled.img` height: 40px; width: auto; `; +// 검색창 스타일 const SearchBar = styled.input.attrs({ type: 'text', placeholder: '검색...' @@ -79,41 +88,43 @@ const SearchBar = styled.input.attrs({ border-radius: 4px; `; +// 사용자 액션 버튼들의 스타일 const UserActions = styled.div` display: flex; align-items: center; `; +// 알림 버튼 스타일 const NotificationButton = styled.button` margin-right: 1rem; background-color: #fff; border: none; cursor: pointer; - img { height: 40px; width: auto; } `; +// 프로필 버튼 스타일 const ProfileButton = styled.button` margin-right: 1rem; - background-color: transparent; // You can adjust this color if needed + background-color: transparent; border: none; cursor: pointer; padding: 0; - &:focus { outline: none; } `; +// 프로필 이미지 스타일 const ProfileImage = styled.img` height: 40px; width: auto; `; - +// 로그아웃 버튼 스타일 const LogoutButton = styled.button` background-color: #fff; color: #2F4F4F; @@ -122,7 +133,6 @@ const LogoutButton = styled.button` border-radius: 5px; cursor: pointer; transition: background-color 0.3s; - &:hover { background-color: #f2f2f2; } @@ -130,3 +140,6 @@ const LogoutButton = styled.button` + + + diff --git a/client/src/components/Headers/LogoutHeader.tsx b/client/src/components/Headers/LogoutHeader.tsx index 9451a272..fd7b155e 100644 --- a/client/src/components/Headers/LogoutHeader.tsx +++ b/client/src/components/Headers/LogoutHeader.tsx @@ -1,11 +1,11 @@ import React, { useState } from "react"; import styled from "styled-components"; import StockHolmLogo from "../../asset/images/StockHolmLogo.png"; -import { useNavigate } from "react-router-dom"; // 라우터의 히스토리를 사용하기 위해 가져옴 +import { useNavigate } from "react-router-dom"; // 라우터의 네비게이션을 사용하기 위해 가져옴 const LogoutHeader: React.FC = ({ onLoginClick }) => { const [searchValue, setSearchValue] = useState(""); // 검색 값 상태 관리 - const navigate = useNavigate(); // 라우터 히스토리 훅 사용 + const navigate = useNavigate(); // 라우터 네비게이션 훅 사용 // 검색 입력 변경 핸들러 const handleSearchChange = (event: React.ChangeEvent) => { @@ -31,6 +31,9 @@ const LogoutHeader: React.FC = ({ onLoginClick }) => { ); }; +export default LogoutHeader; + + // 스타일드 컴포넌트 정의 const HeaderContainer = styled.div` display: flex; @@ -86,4 +89,3 @@ interface LogoutHeaderProps { onLoginClick: () => void; } -export default LogoutHeader; From 88965a3d0b059cdb96c5359af511d505e284def3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=91=ED=98=84?= Date: Tue, 5 Sep 2023 11:30:53 +0900 Subject: [PATCH 03/15] =?UTF-8?q?[Feat]OAuth=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?develop=20=EB=B0=B1=EC=97=94=EB=93=9C=20=EB=A1=9C=EC=BB=AC?= =?UTF-8?q?=EC=9D=B4=20=EC=95=84=EB=8B=8C=20=EB=B0=B1=EC=97=94=EB=93=9C=20?= =?UTF-8?q?=EB=B0=B0=ED=8F=AC=EC=84=9C=EB=B2=84=EC=99=80=20=ED=86=B5?= =?UTF-8?q?=EC=8B=A0=20=EC=A3=BC=EC=84=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/components/Logins/OAuthLogin.tsx | 62 +++++++++------------ 1 file changed, 26 insertions(+), 36 deletions(-) diff --git a/client/src/components/Logins/OAuthLogin.tsx b/client/src/components/Logins/OAuthLogin.tsx index 78e1b1c2..8167de9d 100644 --- a/client/src/components/Logins/OAuthLogin.tsx +++ b/client/src/components/Logins/OAuthLogin.tsx @@ -3,9 +3,9 @@ import googleLogo from '../../asset/images/GoogleLogo.svg'; import kakaoLogo from '../../asset/images/KakaoLogo.svg'; import axios from 'axios'; - - +// OAuth 로그인 모달 컴포넌트 const OAuthLoginModal: React.FC = ({ onClose, onEmailLoginClick, onEmailSignupClick }) => { + // 텍스트 상수 const titleText = "로그인"; const googleLoginText = "구글로 로그인"; const kakaoLoginText = "카카오로 로그인"; @@ -13,12 +13,11 @@ const OAuthLoginModal: React.FC = ({ onClose, onEmailLoginClick const emailLoginText = "이메일로 로그인"; const emailSignupText = "이메일로 회원가입"; - + // 구글 로그인 핸들러 const handleGoogleLogin = async () => { try { - const response = await axios.post('http://localhost:8080/auth/google'); + const response = await axios.post('http://ec2-13-125-246-160.ap-northeast-2.compute.amazonaws.com/oauth2/authorization/google'); if (response.status === 200) { - // 로그인 처리 console.log("Successfully logged in with Google!"); onClose(); } else { @@ -27,13 +26,13 @@ const OAuthLoginModal: React.FC = ({ onClose, onEmailLoginClick } catch (error) { console.error("Error logging in with Google:", error); } - }; - - const handleKakaoLogin = async () => { + }; + + // 카카오 로그인 핸들러 + const handleKakaoLogin = async () => { try { - const response = await axios.post('http://localhost:8080/auth/kakao'); + const response = await axios.post('http://ec2-13-125-246-160.ap-northeast-2.compute.amazonaws.com/oauth2/authorization/kakao'); if (response.status === 200) { - // 로그인 처리 console.log("Successfully logged in with Kakao!"); onClose(); } else { @@ -42,8 +41,9 @@ const OAuthLoginModal: React.FC = ({ onClose, onEmailLoginClick } catch (error) { console.error("Error logging in with Kakao:", error); } - }; - + }; + + // 모달 반환 return ( @@ -53,7 +53,6 @@ const OAuthLoginModal: React.FC = ({ onClose, onEmailLoginClick {googleLoginText} - {kakaoLoginText} @@ -70,27 +69,27 @@ const OAuthLoginModal: React.FC = ({ onClose, onEmailLoginClick export default OAuthLoginModal; +// 로그인 모달 인터페이스 interface LoginModalProps { onClose: () => void; onEmailLoginClick: () => void; - onEmailSignupClick: () => void; // 추가 - onWatchListClick: () => void; // 추가 - onHoldingsClick: () => void; // 추가 + onEmailSignupClick: () => void; + onWatchListClick: () => void; + onHoldingsClick: () => void; } +// 스타일 컴포넌트 const OrText = styled.span` margin: 20px 0; color: grey; `; - const Title = styled.h2` margin-bottom: 20px; - font-size: 1.6rem; // 크기를 줄입니다. - font-weight: 400; // 굵기를 줄입니다. + font-size: 1.6rem; + font-weight: 400; `; - const ModalBackground = styled.div` display: flex; justify-content: center; @@ -131,22 +130,15 @@ const OAuthButton = styled.button` border: 1px solid lightgray; border-radius: 5px; cursor: pointer; - width: 300px; // 버튼의 가로 너비를 동일하게 설정합니다. - display: flex; - align-items: center; - justify-content: center; -`; -const GoogleButton = styled(OAuthButton)` + width: 300px; display: flex; align-items: center; justify-content: center; `; -const KakaoButton = styled(OAuthButton)` - display: flex; - align-items: center; - justify-content: center; -`; +const GoogleButton = styled(OAuthButton)``; + +const KakaoButton = styled(OAuthButton)``; const EmailButtonsContainer = styled.div` display: flex; @@ -155,7 +147,6 @@ const EmailButtonsContainer = styled.div` margin: 5px 0; `; - const EmailButton = styled.button` margin: 5px 0; padding: 10px 20px; @@ -165,9 +156,8 @@ const EmailButton = styled.button` cursor: pointer; `; - const LogoImage = styled.img` margin-right: 30px; - width: 60px; // 로고의 가로 크기를 조정합니다. 필요에 따라 값을 조절할 수 있습니다. - height: auto; // 가로 크기에 맞춰 세로 크기를 자동으로 조절합니다. -`; \ No newline at end of file + width: 60px; + height: auto; +`; From 10403bb78b07febcb92200d30ca0fc35f79a27c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=91=ED=98=84?= Date: Tue, 5 Sep 2023 11:40:45 +0900 Subject: [PATCH 04/15] =?UTF-8?q?[Feat]=EC=9D=B4=EB=A9=94=EC=9D=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20develop?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/components/Logins/EmailLogin.tsx | 61 +++++++++++---------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/client/src/components/Logins/EmailLogin.tsx b/client/src/components/Logins/EmailLogin.tsx index f70866e3..656d0fe1 100644 --- a/client/src/components/Logins/EmailLogin.tsx +++ b/client/src/components/Logins/EmailLogin.tsx @@ -2,14 +2,9 @@ import axios from "axios"; import styled from "styled-components"; import React, { useState } from "react"; -const EmailLoginModal = ({ - onClose, - onLogin, -}: { - onClose: () => void; - onLogin: () => void; -}) => { - // 문자열 변수 정의 +// 이메일 로그인 모달 컴포넌트 +const EmailLoginModal: React.FC = ({ onClose, onLogin }) => { + // 상수 문자열 정의 const titleText = "이메일로 로그인"; const emailLabelText = "이메일"; const passwordLabelText = "비밀번호"; @@ -18,53 +13,52 @@ const EmailLoginModal = ({ const noAccountText = "계정이 없습니까?"; const registerButtonText = "회원가입하기"; - const [email, setEmail] = useState(""); // 입력된 이메일 상태 - const [password, setPassword] = useState(""); // 입력된 비밀번호 상태 + // 상태 변수 정의 + const [email, setEmail] = useState(""); + const [password, setPassword] = useState(""); + // 이메일 변경 핸들러 const handleEmailChange = (event: React.ChangeEvent) => { setEmail(event.target.value); }; + // 비밀번호 변경 핸들러 const handlePasswordChange = (event: React.ChangeEvent) => { setPassword(event.target.value); }; + // 로그인 버튼 클릭 핸들러 const handleLoginClick = async () => { try { + // 백엔드에 로그인 요청 const response = await axios.post("http://localhost:8080/login", { email, password, }); if (response.status === 200) { + // 성공적으로 로그인된 경우, 토큰을 로컬 스토리지에 저장 + const authToken = response.data.authorization; + localStorage.setItem('authToken', authToken); onLogin(); onClose(); } else { - console.error("Error during login"); + console.error("로그인 중 오류 발생"); } } catch (error) { - console.error("Error during login:", error); + console.error("로그인 중 오류:", error); } }; return ( + // 모달 레이아웃 × {titleText} - + - + {findPasswordText} {loginButtonText} @@ -77,6 +71,13 @@ const EmailLoginModal = ({ export default EmailLoginModal; +// 컴포넌트 props 타입 정의 +interface EmailLoginModalProps { + onClose: () => void; + onLogin: () => void; +} + +// 스타일드 컴포넌트 정의 const ModalBackground = styled.div` display: flex; justify-content: center; @@ -112,8 +113,8 @@ const CloseButton = styled.button` const Title = styled.h2` margin-bottom: 20px; - font-size: 1.6rem; // 크기를 줄입니다. - font-weight: 400; // 굵기를 줄입니다. + font-size: 1.6rem; + font-weight: 400; `; const Label = styled.label` @@ -134,7 +135,7 @@ const RightAlignedButton = styled.button` margin-top: 5px; background: none; border: none; - color: slategray; // 글자색을 변경합니다. + color: slategray; cursor: pointer; `; @@ -142,7 +143,7 @@ const LoginButton = styled.button` width: 100%; padding: 10px; margin-top: 10px; - background-color: darkslategray; // 배경색을 변경합니다. + background-color: darkslategray; color: white; border: none; border-radius: 5px; @@ -151,12 +152,12 @@ const LoginButton = styled.button` const BottomText = styled.div` margin-top: 10px; - font-size: 0.9rem; // 크기를 줄입니다. + font-size: 0.9rem; `; const RegisterButton = styled.button` background: none; border: none; - color: slategray; // 글자색을 변경합니다. + color: slategray; cursor: pointer; `; From 4c5f2a952c58e563b6af2510f6cb6728e0f8ff8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=91=ED=98=84?= Date: Tue, 5 Sep 2023 11:42:48 +0900 Subject: [PATCH 05/15] =?UTF-8?q?[Feat]=EC=9D=B4=EB=A9=94=EC=9D=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20develop=20=EB=B0=B1?= =?UTF-8?q?=EC=97=94=EB=93=9C=EA=B0=80=20=EC=A0=84=EC=86=A1=ED=95=98?= =?UTF-8?q?=EB=8A=94=20Authorization=20code=EB=A5=BC=20=EB=A1=9C=EC=BB=AC?= =?UTF-8?q?=EC=97=90=20=EC=A0=80=EC=9E=A5=20=EB=B0=B1=EC=97=94=EB=93=9C=20?= =?UTF-8?q?=EB=A1=9C=EC=BB=AC=EC=9D=B4=20=EC=95=84=EB=8B=8C=20=EB=B0=B0?= =?UTF-8?q?=ED=8F=AC=20=EC=84=9C=EB=B2=84=EC=99=80=20=ED=86=B5=EC=8B=A0=20?= =?UTF-8?q?=EC=A3=BC=EC=84=9D=20=EC=B6=94=EA=B0=80=20Issues#8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/components/Logins/EmailLogin.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/components/Logins/EmailLogin.tsx b/client/src/components/Logins/EmailLogin.tsx index 656d0fe1..a0adb60c 100644 --- a/client/src/components/Logins/EmailLogin.tsx +++ b/client/src/components/Logins/EmailLogin.tsx @@ -31,7 +31,7 @@ const EmailLoginModal: React.FC = ({ onClose, onLogin }) = const handleLoginClick = async () => { try { // 백엔드에 로그인 요청 - const response = await axios.post("http://localhost:8080/login", { + const response = await axios.post("http://ec2-13-125-246-160.ap-northeast-2.compute.amazonaws.com/login", { email, password, }); From a9ee5231186c227cf13bddf8f04535d644a6e7f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=91=ED=98=84?= Date: Tue, 5 Sep 2023 11:49:04 +0900 Subject: [PATCH 06/15] =?UTF-8?q?[Feat]=EC=9D=B4=EB=A9=94=EC=9D=BC?= =?UTF-8?q?=EB=A1=9C=20=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85=20develop=20?= =?UTF-8?q?=EB=B0=B1=EC=97=94=EB=93=9C=20=EB=A1=9C=EC=BB=AC=20=EC=A3=BC?= =?UTF-8?q?=EC=86=8C=EA=B0=80=20=EC=95=84=EB=8B=8C=20=EB=B0=B0=ED=8F=AC=20?= =?UTF-8?q?=EC=A3=BC=EC=86=8C=EB=A1=9C=20=EB=B3=80=EA=B2=BD=20=EC=A3=BC?= =?UTF-8?q?=EC=84=9D=20=EC=B6=94=EA=B0=80=20Issues#8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/components/Signups/EmailSignup.tsx | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/client/src/components/Signups/EmailSignup.tsx b/client/src/components/Signups/EmailSignup.tsx index c5483f73..91706800 100644 --- a/client/src/components/Signups/EmailSignup.tsx +++ b/client/src/components/Signups/EmailSignup.tsx @@ -2,6 +2,7 @@ import axios from 'axios'; import styled from 'styled-components'; import React, { useState } from 'react'; +// 문자열 상수 정의 const strings = { titleText: "이메일로 회원가입", emailLabelText: "이메일", @@ -9,15 +10,19 @@ const strings = { }; const EmailSignupModal: React.FC = ({ onClose, onRequestVerification }) => { - const [email, setEmail] = useState(''); // 입력된 이메일을 관리하는 상태 + // 사용자가 입력한 이메일 상태 + const [email, setEmail] = useState(''); + // 이메일 입력 핸들러 const handleEmailChange = (event: React.ChangeEvent) => { setEmail(event.target.value); }; + // 이메일 인증 요청 핸들러 const handleVerificationRequest = async () => { try { - const response = await axios.post('http://localhost:8080/email/send', { email }); + // 백엔드 배포 주소로 입력받은 이메일 전송 + const response = await axios.post('http://ec2-13-125-246-160.ap-northeast-2.compute.amazonaws.com/email/send', { email }); if (response.status === 200) { onRequestVerification(); } else { @@ -45,12 +50,13 @@ const EmailSignupModal: React.FC = ({ onClose, onRequestV export default EmailSignupModal; - +// 프롭 타입 정의 type EmailSignupModalProps = { onClose: () => void; onRequestVerification: () => void; }; +// 스타일 컴포넌트 정의 const ModalBackground = styled.div` display: flex; justify-content: center; @@ -86,8 +92,7 @@ const CloseButton = styled.button` const Title = styled.h2` margin-bottom: 20px; - font-size: 1.6rem; // 크기를 줄입니다. - font-weight: 400; // 굵기를 줄입니다. + font-size: 1.6rem; `; const Label = styled.label` @@ -107,7 +112,7 @@ const SignupButton = styled.button` width: 100%; padding: 10px; margin-top: 10px; - background-color: darkslategray; // 배경색을 변경합니다. + background-color: darkslategray; color: white; border: none; border-radius: 5px; From 959d94db25a5f1ed9c1e9d3d5879c94f1c7b744a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=91=ED=98=84?= Date: Tue, 5 Sep 2023 12:00:02 +0900 Subject: [PATCH 07/15] =?UTF-8?q?[Feat]=EC=9D=B4=EB=A9=94=EC=9D=BC=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=EC=9D=B8=EC=A6=9D=20develop=20=EB=B0=B1?= =?UTF-8?q?=EC=97=94=EB=93=9C=20=EB=B0=B0=ED=8F=AC=20=EC=A3=BC=EC=86=8C?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD=20=EC=A3=BC=EC=84=9D=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20Issues#8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/Signups/EmailCertify.tsx | 29 ++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/client/src/components/Signups/EmailCertify.tsx b/client/src/components/Signups/EmailCertify.tsx index 722cd87d..62655582 100644 --- a/client/src/components/Signups/EmailCertify.tsx +++ b/client/src/components/Signups/EmailCertify.tsx @@ -2,6 +2,7 @@ import axios from 'axios'; import React, { useState } from 'react'; import styled from 'styled-components'; +// 고정 문자열을 정의 const strings = { titleText: "이메일 인증요청", emailLabelText: "인증할 이메일", @@ -11,21 +12,26 @@ const strings = { termsText: "개인정보 처리방침 및 서비스 이용약관에 동의합니다" }; +// 이메일 인증 모달 컴포넌트 const EmailVerificationModal: React.FC = ({ onClose, onNextStep }) => { - const [email, setEmail] = useState('sample@example.com'); // 이메일 상태 - const [verificationCode, setVerificationCode] = useState(''); // 인증코드 상태 + // 이메일 및 인증코드에 대한 상태를 선언합니다. + const [email, setEmail] = useState('sample@example.com'); + const [verificationCode, setVerificationCode] = useState(''); + // 이메일 입력값을 처리하는 함수 const handleEmailChange = (event: React.ChangeEvent) => { setEmail(event.target.value); }; + // 인증코드 입력값을 처리하는 함수 const handleVerificationCodeChange = (event: React.ChangeEvent) => { setVerificationCode(event.target.value); }; + // 다음 단계 버튼 클릭시 이메일 인증을 처리하는 함수 const handleNextStepClick = async () => { try { - const response = await axios.post('http://localhost:8080/email/confirm', { email, code: verificationCode }); + const response = await axios.post('http://ec2-13-125-246-160.ap-northeast-2.compute.amazonaws.com/email/confirm', { email, code: verificationCode }); if (response.status === 200) { onNextStep(); } else { @@ -60,11 +66,13 @@ const EmailVerificationModal: React.FC = ({ onClose export default EmailVerificationModal; +// 이메일 인증 모달의 Props 타입 type EmailVerificationModalProps = { onClose: () => void; onNextStep: () => void; }; +// 모달의 배경 스타일 const ModalBackground = styled.div` display: flex; justify-content: center; @@ -77,6 +85,7 @@ const ModalBackground = styled.div` background-color: rgba(0, 0, 0, 0.5); `; +// 모달의 컨테이너 스타일 const ModalContainer = styled.div` position: relative; background-color: white; @@ -88,6 +97,7 @@ position: relative; align-items: center; `; +// 모달의 닫기 버튼 스타일 const CloseButton = styled.button` position: absolute; top: 10px; @@ -98,17 +108,19 @@ const CloseButton = styled.button` cursor: pointer; `; +// 제목의 스타일 const Title = styled.h2` margin-bottom: 20px; - font-size: 1.6rem; // 크기를 줄입니다. - font-weight: 400; // 굵기를 줄입니다. + font-size: 1.6rem; `; +// 레이블의 스타일 const Label = styled.label` align-self: flex-start; margin-top: 10px; `; +// 입력 필드의 스타일 const Input = styled.input` width: 100%; padding: 10px; @@ -117,23 +129,26 @@ const Input = styled.input` border-radius: 5px; `; +// 버튼의 스타일 const SignupButton = styled.button` width: 100%; padding: 10px; margin-top: 10px; - background-color: darkslategray; // 배경색을 변경합니다. + background-color: darkslategray; color: white; border: none; border-radius: 5px; cursor: pointer; `; +// 힌트 텍스트의 스타일 const HintText = styled.p` color: red; font-size: 0.8rem; margin-top: 5px; `; +// 이용약관 체크박스의 스타일 const TermsCheckbox = styled.div` margin-top: 10px; display: flex; @@ -146,4 +161,4 @@ const TermsCheckbox = styled.div` label { font-size: 0.9rem; } -`; \ No newline at end of file +`; From 85b9402ca406d4c0a8ee46726d95dd4e6dbf9509 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=91=ED=98=84?= Date: Tue, 5 Sep 2023 12:49:50 +0900 Subject: [PATCH 08/15] =?UTF-8?q?[Feat]=EB=B9=84=EB=B0=80=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=ED=99=95=EC=9D=B8=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20develop=20=EB=B0=B1=EC=97=94=EB=93=9C=20=EB=B0=B0?= =?UTF-8?q?=ED=8F=AC=20=EC=84=9C=EB=B2=84=EB=A1=9C=20=ED=86=B5=EC=8B=A0?= =?UTF-8?q?=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95=20post?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EC=9E=90=EB=A3=8C=EC=97=90=20=EC=9D=B4?= =?UTF-8?q?=EB=A9=94=EC=9D=BC=20=EC=B6=94=EA=B0=80=20post=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=88=9C=EC=84=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20=EC=A3=BC=EC=84=9D=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?Issues#8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/components/Signups/Password.tsx | 42 ++++++++++++++-------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/client/src/components/Signups/Password.tsx b/client/src/components/Signups/Password.tsx index 1a135960..1cf92e5e 100644 --- a/client/src/components/Signups/Password.tsx +++ b/client/src/components/Signups/Password.tsx @@ -2,19 +2,23 @@ import axios from 'axios'; import React, { useState } from 'react'; import styled from 'styled-components'; +// 사용자에게 보여줄 문자열을 정의하는 객체 const strings = { titleText: "비밀번호 설정", passwordLabelText: "비밀번호", confirmPasswordLabelText: "비밀번호 확인", nicknameLabelText: "닉네임", confirmButtonText: "확인" - }; - - const PasswordSettingModal: React.FC<{ onClose: () => void }> = ({ onClose }) => { +}; + +// 비밀번호 설정 모달 컴포넌트 +const PasswordSettingModal: React.FC<{ onClose: () => void, email: string }> = ({ onClose, email }) => { + // 비밀번호, 비밀번호 확인, 닉네임에 대한 상태를 관리합니다. const [password, setPassword] = useState(''); const [confirmPassword, setConfirmPassword] = useState(''); - const [nickname, setNickname] = useState(''); + const [name, setName] = useState(''); + // 각 입력값을 처리하는 핸들러 함수들 const handlePasswordChange = (e: React.ChangeEvent) => { setPassword(e.target.value); }; @@ -23,16 +27,18 @@ const strings = { setConfirmPassword(e.target.value); }; - const handleNicknameChange = (e: React.ChangeEvent) => { - setNickname(e.target.value); + const handleNameChange = (e: React.ChangeEvent) => { + setName(e.target.value); }; + // 확인 버튼 클릭 시 데이터를 서버로 전송하는 함수 const handleConfirmClick = async () => { try { - const response = await axios.post('http://localhost:8080/members', { + const response = await axios.post('http://ec2-13-125-246-160.ap-northeast-2.compute.amazonaws.com/members', { + email, + name, password, confirmPassword, - nickname }); if (response.status === 200) { @@ -47,6 +53,7 @@ const strings = { }; return ( + // 모달의 전체 구조를 정의하는 부분 × @@ -56,15 +63,16 @@ const strings = { - + {strings.confirmButtonText} ); }; - - export default PasswordSettingModal; - + +export default PasswordSettingModal; + +// 모달 배경 스타일 const ModalBackground = styled.div` display: flex; justify-content: center; @@ -77,6 +85,7 @@ const ModalBackground = styled.div` background-color: rgba(0, 0, 0, 0.5); `; +// 모달 컨테이너 스타일 const ModalContainer = styled.div` position: relative; background-color: white; @@ -88,13 +97,14 @@ const ModalContainer = styled.div` align-items: center; `; +// 모달 제목 스타일 const Title = styled.h2` margin-bottom: 20px; font-size: 1.6rem; font-weight: 400; `; - +// 모달 닫기 버튼 스타일 const CloseButton = styled.button` position: absolute; top: 10px; @@ -105,11 +115,13 @@ const CloseButton = styled.button` cursor: pointer; `; +// 레이블 스타일 const Label = styled.label` align-self: flex-start; margin-top: 10px; `; +// 입력 필드 스타일 const Input = styled.input` width: 100%; padding: 10px; @@ -118,7 +130,7 @@ const Input = styled.input` border-radius: 5px; `; - +// 확인 버튼 스타일 const ConfirmButton = styled.button` width: 100%; padding: 10px; @@ -128,4 +140,4 @@ const ConfirmButton = styled.button` border: none; border-radius: 5px; cursor: pointer; -`; \ No newline at end of file +`; From 6d233724091ecfff1b4411e85279a3386f056a10 Mon Sep 17 00:00:00 2001 From: sinjw Date: Tue, 5 Sep 2023 13:27:39 +0900 Subject: [PATCH 09/15] =?UTF-8?q?[Feat]=EA=B2=8C=EC=8B=9C=ED=8C=90?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=84=9C=EB=B2=84=EC=97=B0=EA=B2=B0=20?= =?UTF-8?q?=EA=B2=8C=EC=8B=9C=ED=8C=90=20=EC=97=85=EB=A1=9C=EB=93=9C=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=EB=A7=8C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../communityComponents/TimeLineComponent.tsx | 89 ++++++++++++++----- client/src/data/globalAxios.tsx | 0 client/src/main.tsx | 2 +- 3 files changed, 66 insertions(+), 25 deletions(-) delete mode 100644 client/src/data/globalAxios.tsx diff --git a/client/src/components/communityComponents/TimeLineComponent.tsx b/client/src/components/communityComponents/TimeLineComponent.tsx index 139e1e10..622c87cf 100644 --- a/client/src/components/communityComponents/TimeLineComponent.tsx +++ b/client/src/components/communityComponents/TimeLineComponent.tsx @@ -2,19 +2,30 @@ import { useState, useEffect } from "react"; import styled from "styled-components"; import Comments from "./Comments"; import { DotIcon } from "./IconComponent/Icon"; +import axios from "axios"; + +const serverUrl = + "http://ec2-13-125-246-160.ap-northeast-2.compute.amazonaws.com:8080/boards"; const TimeLineComponent = () => { //로컬스토리지 생성 - const [data, setData] = useState(""); + + const [boardData, setBoardData] = useState([]); + useEffect(() => { - localStorage.setItem("boradData", data); - setData(""); + fetchBoardDataFromServer(); }, []); - const [boardData, setBoardData] = useState(() => { - const storedData = localStorage.getItem("boardData"); - return storedData ? JSON.parse(storedData) : []; - }); + const fetchBoardDataFromServer = async () => { + try { + const response = await axios.get(serverUrl); + const boardData = response.data; + + setBoardData(boardData); + } catch (error) { + console.error("데이터 가져오기 중 오류 발생:", error); + } + }; //드롭다운 버튼 텍스트 작성창 열기 const [openDropDown, setOpenDropDown] = useState(false); @@ -31,27 +42,41 @@ const TimeLineComponent = () => { console.log(inputValue); }; - // 서브밋 버튼 클릭시 로컬스토리지에 작성된 텍스트 저장 - const handleClickSubmit = () => { + // 서브밋 버튼 클릭 + const handleClickSubmit = async () => { if (inputValue.length !== 0) { //if 문의 조건식에 inputValue만 사용해도 정상 작동하는 //이유는 JavaScript와 TypeScript의 "Truthy"와 "Falsy" 값 변환 규칙때문 const newBoardData: BoardData = { id: new Date().getTime(), - boardText: inputValue, + content: inputValue, comments: "", nickname: `user${UserId}`, }; - setBoardData((prevBoardData) => [...prevBoardData, newBoardData]); + try { + const response = await axios.post(`${serverUrl}`, newBoardData); + if (response.status === 201) { + // 서버에 성공적으로 데이터를 업로드한 경우 + alert("작성완료"); + setinputValue(""); // 입력 필드 초기화 + // 서버에서 업데이트된 게시물 목록을 다시 가져오기 + fetchBoardDataFromServer(); + } else { + alert("작성실패"); + } + } catch (error) { + console.log("데이터 추가 중 오류 발생:", error); + alert("작성실패"); + } } else { - return alert("내용이 없습니다"); + alert("내용이 없습니다"); + window.location.href = "http://localhost:5173/community"; } - alert("작성완료"); - window.location.href = "http://localhost:5173/community"; }; //닷버튼 클릭 및 삭제하기 기능 + // const [dotMenuOpen, setDotMenuOpen] = useState(false); const [dotMenuOpenMap, setDotMenuOpenMap] = useState<{ [key: number]: boolean; @@ -64,11 +89,26 @@ const TimeLineComponent = () => { // setDotMenuOpen(!dotMenuOpen); }; - const handleDeleteClick = (id: number) => { - // ID를 사용하여 해당 게시물을 식별하고 삭제 - const deleteData = boardData.filter((el) => el.id !== id); - localStorage.setItem("boardData", JSON.stringify(deleteData)); - window.location.href = "http://localhost:5173/community"; + const handleDeleteClick = async (boardId: number) => { + // boardId로 수정 + try { + const response = await axios.delete(`${serverUrl}/${boardId}`); // URL에 boardId 추가 + if (response.status === 200) { + // 삭제 성공 처리 + alert("삭제되었습니다"); + // 삭제한 게시물을 클라이언트 데이터에서도 제거 + const updatedBoardData = boardData.filter( + (el) => el.boardId !== boardId + ); // boardId로 수정 + setBoardData(updatedBoardData); + } else { + alert("삭제 실패"); + } + } catch (error) { + console.error("데이터 삭제 중 오류 발생:", error); + alert("삭제 실패"); + console.log(boardData); + } }; //유저 아이디 랜덤 설정 const getRandomFourDigitNumber = () => { @@ -79,9 +119,9 @@ const TimeLineComponent = () => { const UserId = getRandomFourDigitNumber(); //boardData업데이트될때 마다 로컬스토리지 데이터 저장 - useEffect(() => { - localStorage.setItem("boardData", JSON.stringify(boardData)); - }, [boardData]); + // useEffect(() => { + // localStorage.setItem("boardData", JSON.stringify(boardData)); + // }, [boardData]); return ( @@ -129,7 +169,7 @@ const TimeLineComponent = () => { {el.nickname}
- {el.boardText} + {el.content}
@@ -143,7 +183,7 @@ export default TimeLineComponent; interface BoardData { id: number; - boardText: string; + content: string; comments: string; nickname: string; } @@ -232,6 +272,7 @@ const SubmitButton = styled.button` //게시판 전체 영역 const BoardArea = styled.div` text-align: center; + margin-top: 25px; width: 90%; `; diff --git a/client/src/data/globalAxios.tsx b/client/src/data/globalAxios.tsx deleted file mode 100644 index e69de29b..00000000 diff --git a/client/src/main.tsx b/client/src/main.tsx index 3d19ea5c..9b42d6a1 100644 --- a/client/src/main.tsx +++ b/client/src/main.tsx @@ -5,7 +5,7 @@ import { QueryClientProvider, QueryClient } from "react-query"; import { Provider } from "react-redux"; import store from "./store/config.ts"; -const queryClient = new QueryClient(); +export const queryClient = new QueryClient(); ReactDOM.createRoot(document.getElementById("root")!).render( From c54db3c8ddd06f2bfa167c23bf881c5756bdc2d4 Mon Sep 17 00:00:00 2001 From: sinjw Date: Tue, 5 Sep 2023 13:41:30 +0900 Subject: [PATCH 10/15] =?UTF-8?q?[Feat]=EC=BB=A4=EB=AE=A4=EB=8B=88?= =?UTF-8?q?=ED=8B=B0=20=EA=B2=8C=EC=8B=9C=ED=8C=90=20=EC=97=85=EB=A1=9C?= =?UTF-8?q?=EB=93=9C=20=EC=84=9C=EB=B2=84=EB=9E=91=EC=97=B0=EA=B2=B0=20?= =?UTF-8?q?=EA=B5=AC=EC=B6=95=20>=20=EA=B2=8C=EC=8B=9C=ED=8C=90=20?= =?UTF-8?q?=EA=B8=80=20=EC=9E=91=EC=84=B1=20=EB=B0=8F=20=EC=97=85=EB=A1=9C?= =?UTF-8?q?=EB=93=9C=EA=B8=B0=EB=8A=A5=20=EC=84=9C=EB=B2=84=EC=99=80=20?= =?UTF-8?q?=EC=97=B0=EA=B2=B0=20>=20=EC=82=AD=EC=A0=9C=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=97=B0=EA=B2=B0=20=ED=95=84=EC=9A=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/components/communityComponents/TimeLineComponent.tsx | 2 -- client/src/main.tsx | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/client/src/components/communityComponents/TimeLineComponent.tsx b/client/src/components/communityComponents/TimeLineComponent.tsx index 622c87cf..f0e9ce38 100644 --- a/client/src/components/communityComponents/TimeLineComponent.tsx +++ b/client/src/components/communityComponents/TimeLineComponent.tsx @@ -8,8 +8,6 @@ const serverUrl = "http://ec2-13-125-246-160.ap-northeast-2.compute.amazonaws.com:8080/boards"; const TimeLineComponent = () => { - //로컬스토리지 생성 - const [boardData, setBoardData] = useState([]); useEffect(() => { diff --git a/client/src/main.tsx b/client/src/main.tsx index 9b42d6a1..3d19ea5c 100644 --- a/client/src/main.tsx +++ b/client/src/main.tsx @@ -5,7 +5,7 @@ import { QueryClientProvider, QueryClient } from "react-query"; import { Provider } from "react-redux"; import store from "./store/config.ts"; -export const queryClient = new QueryClient(); +const queryClient = new QueryClient(); ReactDOM.createRoot(document.getElementById("root")!).render( From abb2f478ca29fb31f841f2eec28410b583c2df2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=91=ED=98=84?= Date: Tue, 5 Sep 2023 13:42:48 +0900 Subject: [PATCH 11/15] =?UTF-8?q?[Fix]=20=EB=B0=B1=EC=97=94=EB=93=9C=20?= =?UTF-8?q?=EC=84=9C=EB=B2=84=20=EC=A3=BC=EC=86=8C=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=ED=8F=AC=ED=8A=B8=EB=A5=BC=208080=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20Issues#2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/components/Logins/EmailLogin.tsx | 2 +- client/src/components/Logins/OAuthLogin.tsx | 4 ++-- client/src/components/Signups/EmailCertify.tsx | 2 +- client/src/components/Signups/EmailSignup.tsx | 2 +- client/src/components/Signups/Password.tsx | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/client/src/components/Logins/EmailLogin.tsx b/client/src/components/Logins/EmailLogin.tsx index a0adb60c..b1b10a31 100644 --- a/client/src/components/Logins/EmailLogin.tsx +++ b/client/src/components/Logins/EmailLogin.tsx @@ -31,7 +31,7 @@ const EmailLoginModal: React.FC = ({ onClose, onLogin }) = const handleLoginClick = async () => { try { // 백엔드에 로그인 요청 - const response = await axios.post("http://ec2-13-125-246-160.ap-northeast-2.compute.amazonaws.com/login", { + const response = await axios.post("http://ec2-13-125-246-160.ap-northeast-2.compute.amazonaws.com:8080/login", { email, password, }); diff --git a/client/src/components/Logins/OAuthLogin.tsx b/client/src/components/Logins/OAuthLogin.tsx index 8167de9d..0a363d69 100644 --- a/client/src/components/Logins/OAuthLogin.tsx +++ b/client/src/components/Logins/OAuthLogin.tsx @@ -16,7 +16,7 @@ const OAuthLoginModal: React.FC = ({ onClose, onEmailLoginClick // 구글 로그인 핸들러 const handleGoogleLogin = async () => { try { - const response = await axios.post('http://ec2-13-125-246-160.ap-northeast-2.compute.amazonaws.com/oauth2/authorization/google'); + const response = await axios.post('http://ec2-13-125-246-160.ap-northeast-2.compute.amazonaws.com:8080/oauth2/authorization/google'); if (response.status === 200) { console.log("Successfully logged in with Google!"); onClose(); @@ -31,7 +31,7 @@ const OAuthLoginModal: React.FC = ({ onClose, onEmailLoginClick // 카카오 로그인 핸들러 const handleKakaoLogin = async () => { try { - const response = await axios.post('http://ec2-13-125-246-160.ap-northeast-2.compute.amazonaws.com/oauth2/authorization/kakao'); + const response = await axios.post('http://ec2-13-125-246-160.ap-northeast-2.compute.amazonaws.com:8080/oauth2/authorization/kakao'); if (response.status === 200) { console.log("Successfully logged in with Kakao!"); onClose(); diff --git a/client/src/components/Signups/EmailCertify.tsx b/client/src/components/Signups/EmailCertify.tsx index 62655582..2bfc6cda 100644 --- a/client/src/components/Signups/EmailCertify.tsx +++ b/client/src/components/Signups/EmailCertify.tsx @@ -31,7 +31,7 @@ const EmailVerificationModal: React.FC = ({ onClose // 다음 단계 버튼 클릭시 이메일 인증을 처리하는 함수 const handleNextStepClick = async () => { try { - const response = await axios.post('http://ec2-13-125-246-160.ap-northeast-2.compute.amazonaws.com/email/confirm', { email, code: verificationCode }); + const response = await axios.post('http://ec2-13-125-246-160.ap-northeast-2.compute.amazonaws.com:8080/email/confirm', { email, code: verificationCode }); if (response.status === 200) { onNextStep(); } else { diff --git a/client/src/components/Signups/EmailSignup.tsx b/client/src/components/Signups/EmailSignup.tsx index 91706800..438c65ce 100644 --- a/client/src/components/Signups/EmailSignup.tsx +++ b/client/src/components/Signups/EmailSignup.tsx @@ -22,7 +22,7 @@ const EmailSignupModal: React.FC = ({ onClose, onRequestV const handleVerificationRequest = async () => { try { // 백엔드 배포 주소로 입력받은 이메일 전송 - const response = await axios.post('http://ec2-13-125-246-160.ap-northeast-2.compute.amazonaws.com/email/send', { email }); + const response = await axios.post('http://ec2-13-125-246-160.ap-northeast-2.compute.amazonaws.com:8080/email/send', { email }); if (response.status === 200) { onRequestVerification(); } else { diff --git a/client/src/components/Signups/Password.tsx b/client/src/components/Signups/Password.tsx index 1cf92e5e..f3ae6e04 100644 --- a/client/src/components/Signups/Password.tsx +++ b/client/src/components/Signups/Password.tsx @@ -34,7 +34,7 @@ const PasswordSettingModal: React.FC<{ onClose: () => void, email: string }> = ( // 확인 버튼 클릭 시 데이터를 서버로 전송하는 함수 const handleConfirmClick = async () => { try { - const response = await axios.post('http://ec2-13-125-246-160.ap-northeast-2.compute.amazonaws.com/members', { + const response = await axios.post('http://ec2-13-125-246-160.ap-northeast-2.compute.amazonaws.com:8080/members', { email, name, password, From 952d9e00ad9436f85ae6c29a55bf521372d2b852 Mon Sep 17 00:00:00 2001 From: sinjw Date: Tue, 5 Sep 2023 14:20:09 +0900 Subject: [PATCH 12/15] =?UTF-8?q?[Feat]=EC=BB=A4=EB=AE=A4=EB=8B=88?= =?UTF-8?q?=ED=8B=B0=20=EA=B8=B0=EB=8A=A5=20=EC=84=9C=EB=B2=84=EC=99=80=20?= =?UTF-8?q?=EC=97=B0=EA=B2=B0=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=20=EB=B0=8F=20=EC=97=85=EB=A1=9C=EB=93=9C=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=84=9C=EB=B2=84=EC=99=80=20=EC=97=B0=EA=B2=B0=20?= =?UTF-8?q?=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EC=82=AD=EC=A0=9C=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=84=9C=EB=B2=84=EC=99=80=EC=97=B0=EA=B2=B0=20?= =?UTF-8?q?=EC=84=9C=EB=B2=84=EC=B8=A1=EC=97=90=EC=84=9C=20=EC=95=BD?= =?UTF-8?q?=EA=B0=84=EC=9D=98=20=EC=88=98=EC=A0=95=20=ED=95=84=EC=9A=94iss?= =?UTF-8?q?ue#7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../communityComponents/TimeLineComponent.tsx | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/client/src/components/communityComponents/TimeLineComponent.tsx b/client/src/components/communityComponents/TimeLineComponent.tsx index f0e9ce38..fe3c7bea 100644 --- a/client/src/components/communityComponents/TimeLineComponent.tsx +++ b/client/src/components/communityComponents/TimeLineComponent.tsx @@ -18,7 +18,6 @@ const TimeLineComponent = () => { try { const response = await axios.get(serverUrl); const boardData = response.data; - setBoardData(boardData); } catch (error) { console.error("데이터 가져오기 중 오류 발생:", error); @@ -49,7 +48,8 @@ const TimeLineComponent = () => { id: new Date().getTime(), content: inputValue, comments: "", - nickname: `user${UserId}`, + title: `user${UserId}`, + boardId: 0, }; try { @@ -155,21 +155,21 @@ const TimeLineComponent = () => { .map((el) => ( -
handleDotOpen(el.id)}> +
handleDotOpen(el.boardId)}>
- {dotMenuOpenMap[el.id] && ( - handleDeleteClick(el.id)}> + {dotMenuOpenMap[el.boardId] && ( + handleDeleteClick(el.boardId)}> 삭제하기 )} - {el.nickname} + {el.title}
{el.content}
- + )) )} @@ -180,10 +180,11 @@ const TimeLineComponent = () => { export default TimeLineComponent; interface BoardData { + boardId: number; id: number; content: string; comments: string; - nickname: string; + title: string; } //드롭다운 글작성 스타일 및 닫기버튼 스타일 From 82dd1494510e6a7155f1d451f39424d61c3559c0 Mon Sep 17 00:00:00 2001 From: sinjw Date: Tue, 5 Sep 2023 14:33:30 +0900 Subject: [PATCH 13/15] =?UTF-8?q?[Feat]=EC=BB=A4=EB=AE=A4=EB=8B=88?= =?UTF-8?q?=ED=8B=B0=20=EA=B2=8C=EC=8B=9C=ED=8C=90=20=EC=84=9C=EB=B2=84?= =?UTF-8?q?=EC=99=80=20=EC=97=B0=EA=B2=B0=20-window.=EC=9D=84=20=ED=86=B5?= =?UTF-8?q?=ED=95=B4=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=ED=95=98=EB=8D=98=20=EB=B6=80=EB=B6=84=EC=9D=84=20useNavigate?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD=20iss?= =?UTF-8?q?ue#7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/communityComponents/TimeLineComponent.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/src/components/communityComponents/TimeLineComponent.tsx b/client/src/components/communityComponents/TimeLineComponent.tsx index fe3c7bea..9a676275 100644 --- a/client/src/components/communityComponents/TimeLineComponent.tsx +++ b/client/src/components/communityComponents/TimeLineComponent.tsx @@ -3,11 +3,12 @@ import styled from "styled-components"; import Comments from "./Comments"; import { DotIcon } from "./IconComponent/Icon"; import axios from "axios"; - +import { useNavigate } from "react-router-dom"; const serverUrl = "http://ec2-13-125-246-160.ap-northeast-2.compute.amazonaws.com:8080/boards"; const TimeLineComponent = () => { + const navigate = useNavigate(); const [boardData, setBoardData] = useState([]); useEffect(() => { @@ -69,7 +70,8 @@ const TimeLineComponent = () => { } } else { alert("내용이 없습니다"); - window.location.href = "http://localhost:5173/community"; + // window.location.href = "http://localhost:5173/community";. + navigate("/community"); } }; From 76a1c0e7432479f409a0fb60b1182bacead8225c Mon Sep 17 00:00:00 2001 From: sinjw Date: Wed, 6 Sep 2023 13:42:37 +0900 Subject: [PATCH 14/15] =?UTF-8?q?[FE]=EC=98=A4=EB=A5=B8=EC=AA=BD=20?= =?UTF-8?q?=ED=83=AD=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EB=94=94=EC=9E=90?= =?UTF-8?q?=EC=9D=B8=20=EC=A0=84=EC=B2=B4=20=EC=83=81=EB=8B=A8=20=ED=83=AD?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EB=94=94=EC=9E=90=EC=9D=B8=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20=EC=84=B8=EB=B6=80=20=ED=83=AD=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=EB=94=94=EC=9E=90=EC=9D=B8=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20Issue#7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MarketComponents/MarketStockList.tsx | 44 +++++++++- .../MarketComponents/MarketSummary.tsx | 74 +++------------- .../communityComponents/TimeLineComponent.tsx | 4 +- client/src/page/MainPage.tsx | 57 +++++++++++-- client/src/page/TabPages/MarketInfoPage.tsx | 58 +++++++++++-- client/src/page/TabPages/TabContainerPage.tsx | 84 +++++++++++++++---- 6 files changed, 220 insertions(+), 101 deletions(-) diff --git a/client/src/components/MarketComponents/MarketStockList.tsx b/client/src/components/MarketComponents/MarketStockList.tsx index a307c250..98625d53 100644 --- a/client/src/components/MarketComponents/MarketStockList.tsx +++ b/client/src/components/MarketComponents/MarketStockList.tsx @@ -1,4 +1,46 @@ +import axios from "axios"; +import { useState, useEffect } from "react"; // useEffect 추가 + +const MarketServerUrl = + "http://ec2-13-125-246-160.ap-northeast-2.compute.amazonaws.com:8080/companies"; + const MarketStockList: React.FC = () => { - return
MarketStockList
; + const [marketStockList, setMarketStockList] = useState([]); // 타입을 명시하고 초기 상태를 빈 배열로 설정 + + useEffect(() => { + // 컴포넌트가 마운트될 때 데이터를 가져오도록 useEffect를 사용 + MarketDataFromServer(); + }, []); + + const MarketDataFromServer = async () => { + try { + const response = await axios.get(MarketServerUrl); + const marketListData = response.data; + setMarketStockList(marketListData); + } catch (error) { + console.error("데이터 가져오기 중 오류 발생:", error); + } + }; + + return ( +
+
종목명
+
현재가
+
변동률
+
거래량
+ {marketStockList.length > 0 ? ( // 데이터가 있는 경우에만 렌더링 + marketStockList.map((el) => ( +
+
{el.korName}
+
{el.code}
+
{el.stockInfResponseDto}
+
+ )) + ) : ( +
Loading...
// 데이터가 로딩 중인 경우 표시 + )} +
+ ); }; + export default MarketStockList; diff --git a/client/src/components/MarketComponents/MarketSummary.tsx b/client/src/components/MarketComponents/MarketSummary.tsx index 87aa8602..b987edf7 100644 --- a/client/src/components/MarketComponents/MarketSummary.tsx +++ b/client/src/components/MarketComponents/MarketSummary.tsx @@ -1,14 +1,8 @@ import styled from "styled-components"; -import { useState } from "react"; + // import { parseString } from "xml2js"; // import axios from "axios"; const MarketSummary: React.FC = () => { - const [selectKospi, setSelectKospi] = useState("kospi"); - const handleKospiClick = (tab: string) => { - setSelectKospi(tab); - - console.log(tab); - }; //컴포넌트 안쪽의 텍스트 변수 //컴포넌트 내부 텍스트 변수로 치환후 사용 @@ -27,63 +21,14 @@ const MarketSummary: React.FC = () => { kospi200: "kospi200", news: "주요 뉴스", }; - // const [rssItems, setRssItems] = useState([]); - - // useEffect(() => { - // const fetchRSSFeed = async () => { - // try { - // const response = await axios.get( - // "https://www.chosun.com/arc/outboundfeeds/rss/category/economy/?outputType=xml" - // ); - - // // RSS 피드 XML을 JavaScript 객체로 파싱 - // parseString(response.data, (err, result) => { - // if (err) { - // console.error("Error parsing XML:", err); - // return; - // } - // // 파싱된 데이터 중에서 아이템 정보 가져오기 - // const items = result.rss.channel[0].item; - - // // 화면에 출력할 데이터를 상태에 저장 - // setRssItems(items); - // }); - // } catch (error) { - // console.error("Error:", error); - // } - // }; - - // fetchRSSFeed(); - // }, []); return ( {SummaryText.now} - -
  • handleKospiClick("kospi")} - className={selectKospi === "kospi" ? "active" : ""} - > - {SummaryText.kospi} -
  • -
  • handleKospiClick("kosdaq")} - className={selectKospi === "kospi" ? "active" : ""} - > - {SummaryText.kosdaq} -
  • -
  • handleKospiClick("kospi200")} - className={selectKospi === "kospi" ? "active" : ""} - > - {SummaryText.kospi200} -
  • -
    - {selectKospi === "kospi" && ( -
    Kospi {/*9UI1TAFMQFM21QAS 알파어드밴티지 api키*/}
    - )} - {selectKospi === "kosdaq" &&
    Kosdq
    } - {selectKospi === "kospi200" &&
    Kospi200
    } + +
    {SummaryText.kospi}
    +
    + {SummaryText.news} > @@ -107,13 +52,14 @@ const News = styled.div` const A = styled.a` color: black; `; -const MarketH3 = styled.h3` - text-align: left; +const MarketH3 = styled.div` + text-align: center; margin-top: 20px; + font-size: 20px; font-weight: bold; - color: red; + color: #2d4f51; `; -const Kospi = styled.ul` +const Kospiul = styled.ul` display: flex; justify-content: space-around; margin-top: 20px; diff --git a/client/src/components/communityComponents/TimeLineComponent.tsx b/client/src/components/communityComponents/TimeLineComponent.tsx index 9a676275..202f6c9c 100644 --- a/client/src/components/communityComponents/TimeLineComponent.tsx +++ b/client/src/components/communityComponents/TimeLineComponent.tsx @@ -70,14 +70,13 @@ const TimeLineComponent = () => { } } else { alert("내용이 없습니다"); - // window.location.href = "http://localhost:5173/community";. + navigate("/community"); } }; //닷버튼 클릭 및 삭제하기 기능 - // const [dotMenuOpen, setDotMenuOpen] = useState(false); const [dotMenuOpenMap, setDotMenuOpenMap] = useState<{ [key: number]: boolean; }>({}); @@ -86,7 +85,6 @@ const TimeLineComponent = () => { ...prevState, [id]: !prevState[id], // 해당 게시물의 상태를 토글 })); - // setDotMenuOpen(!dotMenuOpen); }; const handleDeleteClick = async (boardId: number) => { diff --git a/client/src/page/MainPage.tsx b/client/src/page/MainPage.tsx index c62a047f..e6b7b151 100644 --- a/client/src/page/MainPage.tsx +++ b/client/src/page/MainPage.tsx @@ -50,7 +50,8 @@ const MainPage = () => { setEmailSignupModalOpen(false); }, []); - const [isEmailVerificationModalOpen, setEmailVerificationModalOpen] = useState(false); + const [isEmailVerificationModalOpen, setEmailVerificationModalOpen] = + useState(false); const openEmailVerificationModal = useCallback(() => { setEmailSignupModalOpen(false); // 이메일 회원가입 모달 닫기 @@ -61,7 +62,8 @@ const MainPage = () => { setEmailVerificationModalOpen(false); }, []); - const [isPasswordSettingModalOpen, setPasswordSettingModalOpen] = useState(false); + const [isPasswordSettingModalOpen, setPasswordSettingModalOpen] = + useState(false); const openPasswordSettingModal = useCallback(() => { setEmailVerificationModalOpen(false); // 이메일 인증 모달 닫기 @@ -78,7 +80,9 @@ const MainPage = () => { setIsLoggedIn(true); }; - const [selectedMenu, setSelectedMenu] = useState<"관심목록" | "투자목록">("투자목록"); // Default menu is 관심목록 + const [selectedMenu, setSelectedMenu] = useState<"관심목록" | "투자목록">( + "투자목록" + ); // Default menu is 관심목록 const handleMenuChange = (menu: "관심목록" | "투자목록") => { setSelectedMenu(menu); @@ -90,22 +94,57 @@ const MainPage = () => { return ( - {isLoggedIn ? : } + {isLoggedIn ? ( + + ) : ( + + )}
    {!expandScreen.left && ( - {selectedMenu === "관심목록" ? : } + + {selectedMenu === "관심목록" ? ( + + ) : ( + + )} + )} {!expandScreen.right && }
    {isOAuthModalOpen && ( - handleMenuChange("관심목록")} onHoldingsClick={() => handleMenuChange("투자목록")} /> + handleMenuChange("관심목록")} + onHoldingsClick={() => handleMenuChange("투자목록")} + /> + )} + {isEmailLoginModalOpen && ( + + )} + {isEmailSignupModalOpen && ( + + )} + {isEmailVerificationModalOpen && ( + )} - {isEmailLoginModalOpen && } - {isEmailSignupModalOpen && } - {isEmailVerificationModalOpen && } {isPasswordSettingModalOpen && ( { diff --git a/client/src/page/TabPages/MarketInfoPage.tsx b/client/src/page/TabPages/MarketInfoPage.tsx index 1208484a..194678f4 100644 --- a/client/src/page/TabPages/MarketInfoPage.tsx +++ b/client/src/page/TabPages/MarketInfoPage.tsx @@ -6,18 +6,41 @@ import MarketIssue from "../../components/MarketComponents/MarketIssue"; interface Props {} const MarketInfo: React.FC = () => { const [selectedTab, setSelectedTab] = useState("market"); + const [tabStyle, setTabStyle] = useState(1); const handleTabClick = (tab: string) => { setSelectedTab(tab); - console.log("click"); + }; + const handleTabStyle = (number: number) => { + setTabStyle(number); }; return (
    + + - handleTabClick("market")}>시장요약 - handleTabClick("stockList")}> - 전체종목 - - handleTabClick("issues")}>시장이슈 + handleTabStyle(1)} + className={`tab ${tabStyle === 1 ? "active-tab" : "inactive-tab"}`} + > + handleTabClick("market")}>시장요약 + + handleTabStyle(2)} + className={`tab ${tabStyle === 2 ? "active-tab" : "inactive-tab"}`} + > + handleTabClick("stockList")}> + 전체종목 + + + handleTabStyle(3)} + className={`tab ${tabStyle === 3 ? "active-tab" : "inactive-tab"}`} + > + handleTabClick("issues")}>시장이슈 +
    {selectedTab === "market" && } @@ -31,6 +54,29 @@ const MarketInfo: React.FC = () => { export default MarketInfo; // **스타일 옮기기 + +const TabStyle = styled.div` + cursor: pointer; + + &.active-tab { + transition: all 0.4s; + border: 1px solid#2d4f51; + background-color: #2d4f51; + padding: 10px 30px; + font-size: 14px; + border-radius: 60px 60px; + color: #fff; + font-family: "Noto Sans KR", sans-serif; + } + &.inactive-tab { + border: 1px solid#2d4f51; + padding: 10px; + color: #2d4f51; + font-size: 14px; + border-radius: 60px 60px; + font-family: "Noto Sans KR", sans-serif; + } +`; //시장정보 탭의 프레임 스타일 const MarketInfoStyle = styled.div` display: flex; diff --git a/client/src/page/TabPages/TabContainerPage.tsx b/client/src/page/TabPages/TabContainerPage.tsx index cc0fb48f..2e413ab7 100644 --- a/client/src/page/TabPages/TabContainerPage.tsx +++ b/client/src/page/TabPages/TabContainerPage.tsx @@ -4,16 +4,50 @@ import styled from "styled-components"; import { StockItems } from "../../components/stockListComponents/StockItems"; import { Community } from "./communityPage"; import { Status } from "../../components/statusComponents/Status"; - +import { useState } from "react"; export const TabContainerPage = () => { + const [activeTab, setActiveTab] = useState(1); + const handleClickActiveTab = (number: number) => { + setActiveTab(number); + }; + return ( + +
    - - - - + + + + } /> @@ -29,28 +63,42 @@ export const TabContainerPage = () => { const TabContainerStyle = styled.div` width: 26%; min-width: 400px; - - overflow: hidden; - border: 1px solid black; + overflow: scroll; + border-left: 1px solid #2d4f51; `; const TabNavArea = styled.div` display: flex; width: 100%; - height: 50px; + height: 53px; + margin-bottom: 10px; justify-content: space-around; align-items: center; + + padding-top: 10px; `; const Nav = styled(Link)` - text-align: center; - font-size: 12px; - width: 100px; - height: 30px; - background-color: white; - color: black; - &:focus { - color: red; - transition: all 0.4s; + &.inactive-tab { + text-align: center; + font-size: 14px; + width: 100%; + height: 44px; + font-family: "Noto Sans KR", sans-serif; + color: #2d4f51; + border-bottom: 1px solid#2d4f51; + margin-top: -20px; + padding-top: 15px; + } + &.active-tab { + margin-top: -20px; + padding-top: 15px; + font-family: "Noto Sans KR", sans-serif; + text-align: center; + font-size: 14px; + height: 44px; + width: 100%; + border-bottom: 3px solid#2d4f51; + color: #2d4f51; } `; From cbee1cc2e808ba149dd04de793339a38787f0b1d Mon Sep 17 00:00:00 2001 From: sinjw Date: Wed, 6 Sep 2023 15:26:59 +0900 Subject: [PATCH 15/15] =?UTF-8?q?[Rename]index=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20-=EC=83=81=EB=8B=A8=20=ED=83=AD=20?= =?UTF-8?q?=EB=B6=80=EB=B6=84=20=EB=94=94=EC=9E=90=EC=9D=B8=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20-=EC=B5=9C=EC=83=81=EC=9C=84=20=EC=BB=B4=ED=8D=BC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EB=B0=8F=20=EA=B0=80=EC=9E=A5=EB=A8=BC?= =?UTF-8?q?=EC=A0=80=20=EB=B3=B4=EC=97=AC=EC=A7=80=EB=8A=94=20=EC=BB=B4?= =?UTF-8?q?=ED=8D=BC=EB=84=8C=ED=8A=B8=EC=9D=B4=EB=A6=84=EC=9D=84=20index.?= =?UTF-8?q?tsx=EB=A1=9C=20=EB=B3=80=EA=B2=BD=20issues=20#7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MarketComponents/MarketStockList.tsx | 69 ++++++++++++++----- .../{MarketSummary.tsx => index.tsx} | 23 ++++++- .../{TimeLineComponent.tsx => index.tsx} | 0 .../{Status.tsx => index.tsx} | 0 4 files changed, 73 insertions(+), 19 deletions(-) rename client/src/components/MarketComponents/{MarketSummary.tsx => index.tsx} (65%) rename client/src/components/communityComponents/{TimeLineComponent.tsx => index.tsx} (100%) rename client/src/components/statusComponents/{Status.tsx => index.tsx} (100%) diff --git a/client/src/components/MarketComponents/MarketStockList.tsx b/client/src/components/MarketComponents/MarketStockList.tsx index 98625d53..d29043f9 100644 --- a/client/src/components/MarketComponents/MarketStockList.tsx +++ b/client/src/components/MarketComponents/MarketStockList.tsx @@ -1,12 +1,12 @@ import axios from "axios"; import { useState, useEffect } from "react"; // useEffect 추가 - +import styled from "styled-components"; const MarketServerUrl = "http://ec2-13-125-246-160.ap-northeast-2.compute.amazonaws.com:8080/companies"; const MarketStockList: React.FC = () => { const [marketStockList, setMarketStockList] = useState([]); // 타입을 명시하고 초기 상태를 빈 배열로 설정 - + const [isLoading, setIsLoading] = useState(true); useEffect(() => { // 컴포넌트가 마운트될 때 데이터를 가져오도록 useEffect를 사용 MarketDataFromServer(); @@ -17,30 +17,65 @@ const MarketStockList: React.FC = () => { const response = await axios.get(MarketServerUrl); const marketListData = response.data; setMarketStockList(marketListData); + setIsLoading(false); } catch (error) { console.error("데이터 가져오기 중 오류 발생:", error); + setIsLoading(false); } }; + const SortName = () => { + // 정렬 함수를 수정하여 즉시 정렬 적용 + const sortedList = [...marketStockList]; + sortedList.sort((a, b) => a.korName.localeCompare(b.korName)); + setMarketStockList(sortedList); + }; return (
    -
    종목명
    -
    현재가
    -
    변동률
    -
    거래량
    - {marketStockList.length > 0 ? ( // 데이터가 있는 경우에만 렌더링 - marketStockList.map((el) => ( -
    -
    {el.korName}
    -
    {el.code}
    -
    {el.stockInfResponseDto}
    -
    - )) - ) : ( -
    Loading...
    // 데이터가 로딩 중인 경우 표시 - )} + + #종목명 + #현재가 + #변동률 + #거래량 + + + {marketStockList.map((el) => ( +
    + {isLoading === true ? ( +
    isLoading...
    + ) : ( + + {el.korName} + + )} + {el.code} +
    + {el.stockInfResponseDto} +
    + ))}
    ); }; export default MarketStockList; + +const StockListTitle = styled.div` + display: flex; + justify-content: space-around; + margin-top: 20px; + margin-bottom: 20px; +`; +const StockListDetail = styled.div` + padding: 5px 5px; + font-size: 12px; + border: 1px solid#333; + border-radius: 20px 20px; + cursor: pointer; + transition: all.3s; + &:hover { + padding: 5px 20px; + } +`; +const StockName = styled.div``; +const StockCode = styled.div``; +const StockInfo = styled.div``; diff --git a/client/src/components/MarketComponents/MarketSummary.tsx b/client/src/components/MarketComponents/index.tsx similarity index 65% rename from client/src/components/MarketComponents/MarketSummary.tsx rename to client/src/components/MarketComponents/index.tsx index b987edf7..913c98e5 100644 --- a/client/src/components/MarketComponents/MarketSummary.tsx +++ b/client/src/components/MarketComponents/index.tsx @@ -1,10 +1,28 @@ import styled from "styled-components"; +import axios from "axios"; +import { useState, useEffect } from "react"; -// import { parseString } from "xml2js"; -// import axios from "axios"; const MarketSummary: React.FC = () => { //컴포넌트 안쪽의 텍스트 변수 //컴포넌트 내부 텍스트 변수로 치환후 사용 + const KospiDataServerUrl = + "http://ec2-13-125-246-160.ap-northeast-2.compute.amazonaws.com:8080/kospi"; + useEffect(() => { + // 컴포넌트가 마운트될 때 데이터를 가져오도록 useEffect를 사용 + KospiDataFromServer(); + }, []); + + const KospiDataFromServer = async () => { + try { + const response = await axios.get(KospiDataServerUrl); + const KospiData = response.data; + setKospiDatas(KospiData); + console.log(kospiDatas, "kospi"); + } catch (error) { + console.error("데이터 가져오기 중 오류 발생:", error); + } + }; + const [kospiDatas, setKospiDatas] = useState([]); interface StockStatus { now: string; @@ -27,6 +45,7 @@ const MarketSummary: React.FC = () => { {SummaryText.now}
    {SummaryText.kospi}
    +
    diff --git a/client/src/components/communityComponents/TimeLineComponent.tsx b/client/src/components/communityComponents/index.tsx similarity index 100% rename from client/src/components/communityComponents/TimeLineComponent.tsx rename to client/src/components/communityComponents/index.tsx diff --git a/client/src/components/statusComponents/Status.tsx b/client/src/components/statusComponents/index.tsx similarity index 100% rename from client/src/components/statusComponents/Status.tsx rename to client/src/components/statusComponents/index.tsx