diff --git a/client/src/components/Headers/LoginHeader.tsx b/client/src/components/Headers/LoginHeader.tsx index 87925c97..b9889b7b 100644 --- a/client/src/components/Headers/LoginHeader.tsx +++ b/client/src/components/Headers/LoginHeader.tsx @@ -1,13 +1,16 @@ + import React, { useState } from 'react'; import styled from 'styled-components'; import StockHolmLogo from "../../asset/images/StockHolmLogo.png"; import SampleProfile from "../../asset/images/ProfileSample.png"; import { useNavigate } from "react-router-dom"; import AlarmImage from "../../asset/images/alarm.png"; +import ProfileModal from "../Profile/profileModal"; // 로그인 상태일 때의 헤더 컴포넌트 const LoginHeader: React.FC = ({ onLogoutClick }) => { + const [isProfileModalOpen, setProfileModalOpen] = useState(false); // 프로필 모달 상태 const [searchValue, setSearchValue] = useState(''); // 검색어 상태 const navigate = useNavigate(); // 페이지 이동 함수 @@ -17,6 +20,15 @@ const LoginHeader: React.FC = ({ onLogoutClick }) => { }; const logoutText = "로그아웃"; + // 프로필 모달 열기 함수 + const handleProfileOpen = () => { + setProfileModalOpen(true); + }; + + // 프로필 모달 닫기 함수 + const handleProfileClose = () => { + setProfileModalOpen(false); + }; // 로고 클릭 처리 함수 const handleLogoClick = () => { @@ -33,9 +45,10 @@ const LoginHeader: React.FC = ({ onLogoutClick }) => { Notification - + + {isProfileModalOpen && } {logoutText} @@ -47,6 +60,7 @@ export default LoginHeader; // 로그아웃 클릭 이벤트 타입 정의 interface LoginHeaderProps { onLogoutClick: () => void; + onProfileClick: () => void; } // 헤더 컨테이너 스타일 @@ -140,7 +154,3 @@ const LogoutButton = styled.button` `; - - - - diff --git a/client/src/components/Logins/LoginConfirmatationModal.tsx b/client/src/components/Logins/LoginConfirmatationModal.tsx index 8aa63659..2ac20066 100644 --- a/client/src/components/Logins/LoginConfirmatationModal.tsx +++ b/client/src/components/Logins/LoginConfirmatationModal.tsx @@ -1,25 +1,48 @@ -// LoginConfirmationModal.tsx -import React from 'react'; +import React, { useEffect } from 'react'; import styled from 'styled-components'; +import { useSelector, useDispatch } from 'react-redux'; +import { setMemberInfo } from '../../reducer/member/memberInfoSlice.ts'; +import useGetMemberInfo from '../../hooks/useGetmemberInfo.ts'; +import { RootState } from '../../reducer/member/rootReducer'; const LoginConfirmationModal: React.FC = ({ onClose }) => { - const messageText = "로그인이 성공적으로 완료되었습니다!"; - const confirmText = "확인" + const messageText = "로그인이 성공적으로 완료되었습니다!"; + const confirmText = "확인" + const loadingText = "로딩 중..."; + const errorText = "데이터를 가져오는 중 문제가 발생했습니다."; - return ( - - - {messageText} - {confirmText} - - - ); + const memberId: number | null = useSelector((state: RootState) => state.login.memberId); + + const { data, error, isLoading } = useGetMemberInfo(memberId); + + const dispatch = useDispatch(); + + useEffect(() => { + if (data) { + dispatch(setMemberInfo(data)); + } + }, [data, dispatch]); + + return ( + + + {isLoading ? ( + {loadingText} + ) : error ? ( + {errorText} + ) : ( + {messageText} + )} + {confirmText} + + + ); }; export default LoginConfirmationModal; interface LoginConfirmationProps { - onClose: () => void; + onClose: () => void; } // ... Styled Components for ModalBackground, ModalContainer, Message, ConfirmButton ... diff --git a/client/src/components/Profile/memberInfoModal.tsx b/client/src/components/Profile/memberInfoModal.tsx index bf0842ef..9d60792b 100644 --- a/client/src/components/Profile/memberInfoModal.tsx +++ b/client/src/components/Profile/memberInfoModal.tsx @@ -1,28 +1,22 @@ -import React, { useState, useEffect } from 'react'; -import styled from 'styled-components'; -import axios from 'axios'; +import React from 'react'; +import styled from 'styled-components'; +import { useSelector } from 'react-redux'; +import useGetMemberInfo from '../../hooks/useGetmemberInfo'; +import { RootState } from '../../store/config'; -const MemberInfoModal: React.FC = ({ onClose, memberId }) => { - const [memberInfo, setMemberInfo] = useState(null); // Use the MemberData type +const MemberInfoModal: React.FC = ({ onClose }) => { + // loginSlice에서 memberId 값을 가져옵니다. + const memberId = useSelector((state: RootState) => state.login.memberId); + + // memberId 값을 useGetMemberInfo 훅에 전달하여 회원 정보를 가져옵니다. + const { data: memberInfo } = useGetMemberInfo(memberId); const titleText = "회원정보"; - const loadingText = "Loading..."; const nameText = "이름: "; const emailText = "이메일: "; const createdAtText = "회원 가입 일시: "; const memberIdText = "회원 ID: "; - useEffect(() => { - // Fetch member info when the modal is opened - axios.get(`http://ec2-13-125-246-160.ap-northeast-2.compute.amazonaws.com/members/${memberId}`) - .then(response => { - setMemberInfo(response.data); - }) - .catch(error => { - console.error("Error fetching member info:", error); - }); - }, [memberId]); - return ( @@ -30,14 +24,13 @@ const MemberInfoModal: React.FC = ({ onClose, memberId }) {titleText} {memberInfo ? (
- {/* Display member information */}

{memberIdText}{memberInfo.memberId}

{nameText}{memberInfo.name}

{emailText}{memberInfo.email}

{createdAtText}{memberInfo.createdAt}

) : ( -

{loadingText}

+
Data not available
)}
@@ -46,15 +39,10 @@ const MemberInfoModal: React.FC = ({ onClose, memberId }) interface MemberInfoModalProps { onClose: () => void; - memberId: string; -} -interface MemberData { - memberId: number; - email: string; - name: string; - createdAt: string; } + + // Styled Components Definitions: const ModalBackground = styled.div` diff --git a/client/src/components/Profile/profileModal.tsx b/client/src/components/Profile/profileModal.tsx index 73b37bca..9f356cc0 100644 --- a/client/src/components/Profile/profileModal.tsx +++ b/client/src/components/Profile/profileModal.tsx @@ -1,5 +1,6 @@ import React, { useState } from 'react'; import styled from 'styled-components'; +import MemberInfoModal from './memberInfoModal'; // 경로는 실제 파일 위치에 따라 수정해야 합니다. const ProfileModal: React.FC = ({ onClose }) => { const [selectedTab, setSelectedTab] = useState(1); @@ -14,12 +15,11 @@ const ProfileModal: React.FC = ({ onClose }) => { × handleTabChange(1)}>회원정보 - handleTabChange(2)}>현금 handleTabChange(3)}>회원탈퇴 - {selectedTab === 1 &&
회원정보 Content
} + {selectedTab === 1 && } {selectedTab === 2 &&
현금 Content
} {selectedTab === 3 &&
회원탈퇴 Content
}
diff --git a/client/src/hooks/useGetMemberInfo.ts b/client/src/hooks/useGetMemberInfo.ts new file mode 100644 index 00000000..2df3cc24 --- /dev/null +++ b/client/src/hooks/useGetMemberInfo.ts @@ -0,0 +1,16 @@ +import { useQuery } from 'react-query'; +import axios from 'axios'; + +function useGetMemberInfo(memberId: number | null) { + return useQuery(['member', memberId], async () => { + const response = await axios.get(`http://ec2-13-125-246-160.ap-northeast-2.compute.amazonaws.com:8080/members/${memberId}`); + + if (response.status === 200) { + return response.data; + } else { + throw new Error('Failed to fetch member data'); + } + }); +} + +export default useGetMemberInfo; \ No newline at end of file diff --git a/client/src/page/MainPage.tsx b/client/src/page/MainPage.tsx index e09e2824..570062e8 100644 --- a/client/src/page/MainPage.tsx +++ b/client/src/page/MainPage.tsx @@ -17,6 +17,8 @@ import CompareChartSection from "../components/CompareChartSection/Index"; import StockOrderSection from "../components/StockOrderSection/Index"; import Welcome from "../components/Signups/Welcome"; +import ProfileModal from "../components/Profile/profileModal"; + import { StateProps } from "../models/stateProps"; import { TabContainerPage } from "./TabPages/TabContainerPage"; @@ -29,6 +31,7 @@ const MainPage = () => { const [isEmailSignupModalOpen, setEmailSignupModalOpen] = useState(false); const [userEmail, setUserEmail] = useState(""); const [isWelcomeModalOpen, setWelcomeModalOpen] = useState(false); + const [isProfileModalOpen, setProfileModalOpen] = useState(false); //프로필 모달 보이기/숨기기 const openOAuthModal = useCallback(() => { setOAuthModalOpen(true); @@ -91,7 +94,10 @@ const MainPage = () => { const [isLoggedIn, setIsLoggedIn] = useState(false); // 로그인 상태 관리 - + //프로필 모달 열고닫는 매커니즘 + const openProfileModal = useCallback(() => { + setProfileModalOpen(true); + }, []); const [isLoginConfirmationModalOpen, setLoginConfirmationModalOpen] = useState(false); @@ -117,7 +123,7 @@ const MainPage = () => { return ( - {isLoggedIn ? : } + {isLoggedIn ? : }
{!expandScreen.left && ( @@ -152,7 +158,9 @@ const MainPage = () => { closeWelcomeModal(); }} /> - )} + )} + {isProfileModalOpen && setProfileModalOpen(false)} />} //프로필 모달 컴포넌트 렌더링 + ); }; diff --git a/client/src/reducer/member/memberInfoSlice.ts b/client/src/reducer/member/memberInfoSlice.ts index 0fc1a056..70e2e2ee 100644 --- a/client/src/reducer/member/memberInfoSlice.ts +++ b/client/src/reducer/member/memberInfoSlice.ts @@ -1,12 +1,12 @@ // memberInfoSlice.ts -import { createSlice, PayloadAction } from '@reduxjs/toolkit'; +import { createSlice, PayloadAction} from '@reduxjs/toolkit'; interface MemberInfo { + memberId: number; email: string; name: string; - password: string; - confirmPassword: string; + createdAt: string; } interface MemberInfoState { @@ -20,16 +20,18 @@ const initialState: MemberInfoState = { }; const memberInfoSlice = createSlice({ - name: 'memberInfo', - initialState, - reducers: { - setMemberInfo: (state, action: PayloadAction) => { - state.memberInfo = action.payload; + name: 'memberInfo', + initialState, + reducers: { + setMemberInfo: (state, action: PayloadAction) => { + state.memberInfo = action.payload; + }, + setEmailForVerification: (state, action: PayloadAction) => { + state.emailForVerification = action.payload; + }, }, - setEmailForVerification: (state, action: PayloadAction) => { - state.emailForVerification = action.payload; // 액션 추가 - }, - }, + + }); export const { setMemberInfo, setEmailForVerification } = memberInfoSlice.actions; diff --git a/client/src/reducer/member/rootReducer.ts b/client/src/reducer/member/rootReducer.ts new file mode 100644 index 00000000..11ff01a0 --- /dev/null +++ b/client/src/reducer/member/rootReducer.ts @@ -0,0 +1,11 @@ +import { combineReducers } from '@reduxjs/toolkit'; +import loginReducer from './loginSlice'; +import memberInfoReducer from './memberInfoSlice'; + +const rootReducer = combineReducers({ + login: loginReducer, + memberInfo: memberInfoReducer, + +}); + +export type RootState = ReturnType; \ No newline at end of file diff --git a/client/src/store/config.ts b/client/src/store/config.ts index 737c02e5..becb5721 100644 --- a/client/src/store/config.ts +++ b/client/src/store/config.ts @@ -23,3 +23,5 @@ const store = configureStore({ }); export default store; + +export type RootState = ReturnType; \ No newline at end of file