diff --git a/src/apis/authAxios.ts b/src/apis/authAxios.ts
index 3ea4925..caa0850 100644
--- a/src/apis/authAxios.ts
+++ b/src/apis/authAxios.ts
@@ -12,10 +12,8 @@ export const getAuthAxios = (accessToken?: string) => {
const authAxios = axios.create({
baseURL: 'http://13.124.54.157:8080',
- headers: {
- 'Content-Type': 'application/json',
- Authorization: `Bearer ${accessToken}`,
- },
+ headers: headersOption,
+ withCredentials: true,
});
authAxios.interceptors.response.use(async (response) => {
diff --git a/src/apis/mypage.ts b/src/apis/mypage.ts
index 9b9db74..b3b0739 100644
--- a/src/apis/mypage.ts
+++ b/src/apis/mypage.ts
@@ -1,7 +1,7 @@
import { getAuthAxios } from './authAxios';
/** MYPAGE API */
-export const getMyPage = async () => {
+export const getUserInfo = async () => {
const access = localStorage.getItem('access');
if (!access) {
@@ -14,3 +14,48 @@ export const getMyPage = async () => {
console.log(response.data);
return response.data;
};
+
+/** MYPAGE 이미지 수정 */
+export const putImage = async () => {
+ const access = localStorage.getItem('access');
+
+ if (!access) {
+ console.error('Access token is missing or invalid');
+ throw new Error('Access token is missing or invalid');
+ }
+
+ const authAxios = getAuthAxios(access);
+ const response = await authAxios.put('/api/mypage/users/image');
+ console.log(response.data);
+ return response.data;
+};
+
+interface MypagePosts {
+ pageParam: number;
+ problemType: 'created' | 'liked' | 'solved';
+}
+
+/** MYPAGE 게시글 조회 */
+export const getMypagePosts = async ({ pageParam = 0, problemType }: MypagePosts) => {
+ const access = localStorage.getItem('access');
+
+ if (!access) {
+ console.error('Access token is missing or invalid');
+ throw new Error('Access token is missing or invalid');
+ }
+
+ const authAxios = getAuthAxios(access);
+
+ // problemType을 헤더에 포함하여 요청을 보냅니다.
+ const response = await authAxios.get('/api/mypage/posts', {
+ headers: {
+ problemType: problemType,
+ },
+ params: {
+ page: pageParam,
+ },
+ });
+
+ console.log(response.data);
+ return response.data;
+};
diff --git a/src/apis/userapi.ts b/src/apis/userapi.ts
index feed6de..b9f1367 100644
--- a/src/apis/userapi.ts
+++ b/src/apis/userapi.ts
@@ -36,7 +36,21 @@ export const postSignup = async ({
};
export const logout = () => {
- // 로컬 스토리지에서 토큰 제거
localStorage.removeItem('access');
window.location.href = '/login';
};
+
+/** 유저정보 수정 */
+export const putUser = async () => {
+ const access = localStorage.getItem('access');
+
+ if (!access) {
+ console.error('Access token is missing or invalid');
+ throw new Error('Access token is missing or invalid');
+ }
+
+ const authAxios = getAuthAxios(access);
+ const response = await authAxios.put('/api/mypage/users');
+ console.log(response.data);
+ return response.data;
+};
diff --git a/src/components/loginForm/index.tsx b/src/components/loginForm/index.tsx
index f471be5..2c855d0 100644
--- a/src/components/loginForm/index.tsx
+++ b/src/components/loginForm/index.tsx
@@ -83,7 +83,9 @@ export default function LoginForm() {
회원가입
- 로그인
+
+ 로그인
+
간편하게 로그인하세요!
diff --git a/src/components/loginForm/styles.ts b/src/components/loginForm/styles.ts
index f33741b..87625cf 100644
--- a/src/components/loginForm/styles.ts
+++ b/src/components/loginForm/styles.ts
@@ -35,19 +35,19 @@ export const Blank = styled.div`
export const Signup = styled.div`
display: flex;
- flex-direction: row;
justify-content: center;
+ gap: 25px;
margin: 30px 0;
color: ${colors.gray300};
p {
- margin-left: 25px;
color: ${colors.yellow};
}
`;
export const Social = styled.div`
${layoutMap.flexCenter}
+ gap: 25px;
margin: 20px 0;
width: 70%;
color: ${colors.gray300};
@@ -60,11 +60,12 @@ export const Social = styled.div`
export const KakaoButton = styled.button`
${layoutMap.styledButton}
background: ${colors.kakao};
- padding: 16px;
- margin: 25px 0;
+ border: 1px solid ${colors.kakao};
+ width: 100%;
`;
export const GoogleButton = styled.button`
${layoutMap.styledButton}
border: 1px solid ${colors.gray};
+ width: 100%;
`;
diff --git a/src/components/mypage/tabMenu/styles.ts b/src/components/mypage/tabMenu/styles.ts
index d677722..2a146b5 100644
--- a/src/components/mypage/tabMenu/styles.ts
+++ b/src/components/mypage/tabMenu/styles.ts
@@ -1,5 +1,5 @@
-//import { layoutMap } from '@/styles/layout';
import { colors } from '@/styles/colorPalette';
+import { typographyMap } from '@/styles/typography';
import styled from '@emotion/styled';
export const Container = styled.div`
@@ -11,9 +11,11 @@ export const TabMenu = styled.ul`
display: flex;
justify-content: space-around;
border-bottom: 1px solid ${colors.gray};
+ ${typographyMap.t2}
`;
export const TabBox = styled.li<{ active: boolean }>`
- padding: 0 90px 20px;
- border-bottom: ${({ active }) => (active ? `5px solid ${colors.yellow}` : 'none')};
+ padding: 0 80px 16px;
+ border-bottom: ${({ active }) => (active ? `8px solid ${colors.yellow}` : 'none')};
+ color: ${({ active }) => (active ? `${colors.yellowActive}` : 'black')};
`;
diff --git a/src/components/mypage/userInfo/index.tsx b/src/components/mypage/userInfo/index.tsx
index 2b1f053..a50bf00 100644
--- a/src/components/mypage/userInfo/index.tsx
+++ b/src/components/mypage/userInfo/index.tsx
@@ -1,23 +1,25 @@
-import { UserCircle } from '@/components/shared/index.ts';
+import { Icon, UserCircle } from '@/components/shared/index.ts';
import * as S from './styles.ts';
import { useEffect, useState } from 'react';
-import { Link } from 'react-router-dom';
-import { getMyPage } from '@/apis/mypage.ts';
+import { useNavigate } from 'react-router-dom';
+import { getUserInfo } from '@/apis/mypage.ts';
import { User } from '@/types/auth.ts';
+import { IconValues } from '@/components/shared/icon/index.tsx';
const UserInfo = () => {
+ const navigate = useNavigate();
const [userData, setUserData] = useState({
- email: '',
- nickname: '',
- github: '',
- blog: '',
- introduce: '',
+ email: 'email.com',
+ nickname: 'Soo',
+ github: 'github',
+ blog: 'blog',
+ introduce: 'ss',
profileImage: '',
});
useEffect(() => {
const fetchUserData = async () => {
- const data = await getMyPage();
+ const data = await getUserInfo();
if (data) {
setUserData({
email: data.email,
@@ -27,23 +29,41 @@ const UserInfo = () => {
introduce: data.introduce,
profileImage: data.profileImageResDto?.fileUrl,
});
+ } else {
+ navigate('/login');
}
};
fetchUserData();
}, []);
+ const contactInfo = [
+ { key: 'email', value: userData.email, icon: 'email' },
+ { key: 'github', value: userData.github, icon: 'github' },
+ { key: 'blog', value: userData.blog, icon: 'blog' },
+ ];
+
return (
-
- 편집
-
+ navigate('profile')}>
+
+
{userData.nickname}
- {userData.email}
+
+ {contactInfo.map(
+ (info) =>
+ info.value && (
+
+
+ {info.value}
+
+ ),
+ )}
+
{userData.introduce}
diff --git a/src/components/mypage/userInfo/styles.ts b/src/components/mypage/userInfo/styles.ts
index 322ea8b..46c5f57 100644
--- a/src/components/mypage/userInfo/styles.ts
+++ b/src/components/mypage/userInfo/styles.ts
@@ -1,12 +1,13 @@
import { colors } from '@/styles/colorPalette';
+import { typographyMap } from '@/styles/typography';
import styled from '@emotion/styled';
export const Container = styled.div`
position: relative;
display: flex;
- padding: 50px 80px;
+ padding: 50px 150px;
width: 100%;
- min-height: 320px;
+ min-height: 300px;
`;
export const LeftBox = styled.div`
@@ -25,27 +26,36 @@ export const ProfileImage = styled.img`
`;
export const UserName = styled.div`
- font-size: 36px;
- font-weight: 700;
+ ${typographyMap.t1}
+ ${typographyMap.bold}
+`;
+
+export const Contact = styled.div`
+ display: flex;
+ align-items: center;
+ margin-top: 12px;
+ gap: 20px;
+`;
+
+export const Block = styled.div`
+ display: flex;
+ align-items: center;
+ gap: 8px;
`;
export const UserEmail = styled.div`
- font-size: 20px;
- color: ${colors.gray200};
+ ${typographyMap.t3}
+ color: ${colors.gray};
`;
export const UserIntro = styled.div`
- margin-top: 50px;
- font-size: 25px;
+ margin-top: 28px;
+ ${typographyMap.t2}
color: ${colors.gray300};
`;
export const Edit = styled.button`
+ display: relative;
position: absolute;
- right: 60px;
- padding: 5px 25px;
- background-color: ${colors.gray100};
- border-radius: 30px;
- font-size: 20px;
- font-weight: 700;
+ right: 150px;
`;
diff --git a/src/components/nav/Nav.tsx b/src/components/nav/Nav.tsx
index 247ccbc..c246ddb 100644
--- a/src/components/nav/Nav.tsx
+++ b/src/components/nav/Nav.tsx
@@ -1,30 +1,30 @@
-import { navItems } from "./navItems";
-import { Icon } from "../shared";
-import { Link } from "react-router-dom";
+import { navItems } from './navItems';
+import { Icon, StyledButton } from '../shared';
+import { Link } from 'react-router-dom';
import * as S from './styles';
const Nav = () => {
- return (
-
-
-
-
-
-
-
- {navItems.map(item => (
-
-
- {item.label}
-
- ))}
-
-
- Post
-
-
- )
-}
+ return (
+
+
+
+
+
+
+
+ {navItems.map((item) => (
+
+
+ {item.label}
+
+ ))}
+
+
+ Post
+
+
+ );
+};
-export default Nav;
\ No newline at end of file
+export default Nav;
diff --git a/src/components/nav/styles.ts b/src/components/nav/styles.ts
index 98a3128..286a667 100644
--- a/src/components/nav/styles.ts
+++ b/src/components/nav/styles.ts
@@ -1,89 +1,67 @@
-import styled from "@emotion/styled";
-import { colors } from "../../styles/colorPalette";
-
+import styled from '@emotion/styled';
+import { colors } from '../../styles/colorPalette';
+import { typographyMap } from '@/styles/typography';
export const NavContainer = styled.div`
- position : sticky;
- top : 0;
- left : 0;
- width : 400px;
- height : 100%;
- padding : 50px 50px;
- box-sizing : border-box;
- display : flex;
- flex-direction : column;
- align-items : center;
- justify-content : flex-start;
- gap : 50px;
+ position: sticky;
+ top: 0;
+ left: 0;
+ width: 400px;
+ height: 100%;
+ padding: 50px 50px;
+ box-sizing: border-box;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: flex-start;
+ gap: 50px;
+ ${typographyMap.t1}
`;
export const NavLogoBox = styled.div`
- width : 100%;
- height : 40px;
- display : flex;
- align-items : center;
- justify-content : center;
+ width: 100%;
+ height: 40px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
- img {
- width : 100%;
- height : 100%;
- object-fit : contain;
- }
+ img {
+ width: 100%;
+ height: 100%;
+ object-fit: contain;
+ }
`;
export const NavItemBox = styled.div`
- width : 100%;
- height : auto;
- display : flex;
- flex-direction : column;
- align-items : center;
- justify-content : center;
- gap : 30px;
- background-color : white;
-
- a {
- text-decoration : none;
- width : 100%;
- height : 50px;
- padding : 0 0 0 30px;
- box-sizing : border-box;
- display : flex;
- align-items : center;
- justify-content : flex-start;
- gap : 20px;
- transition : all 0.1s ease;
-
- p {
- font-size : 36px;
- font-weight : 700;
- color : black;
- }
+ width: 100%;
+ height: auto;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ gap: 30px;
+ background-color: white;
- &:hover {
- cursor : pointer;
- background-color : ${colors.gray50};
- }
- }
-`;
+ a {
+ text-decoration: none;
+ width: 100%;
+ height: 50px;
+ padding: 0 0 0 30px;
+ box-sizing: border-box;
+ display: flex;
+ align-items: center;
+ justify-content: flex-start;
+ gap: 20px;
+ transition: all 0.1s ease;
-export const NavPostBtn = styled.button`
- width : 100%;
- height : 60px;
- display : flex;
- align-items : center;
- justify-content : center;
- background-color : ${colors.yellow};
- border : none;
- border-radius : 999px;
-
- a {
- color : white;
- font-size : 36px;
- font-weight : bold;
+ p {
+ font-weight: 700;
+ color: black;
}
&:hover {
- cursor: pointer;
- background-color : ${colors.yellowHover};
+ cursor: pointer;
+ background-color: ${colors.gray50};
}
-`;
\ No newline at end of file
+ }
+`;
diff --git a/src/components/shared/StyledButton.ts b/src/components/shared/StyledButton.ts
index 2f925f9..af7b3c2 100644
--- a/src/components/shared/StyledButton.ts
+++ b/src/components/shared/StyledButton.ts
@@ -1,23 +1,26 @@
import styled from '@emotion/styled';
import { Colors, colors } from '@/styles/colorPalette';
+import { layoutMap } from '@/styles/layout';
+import { Typograph, typographyMap } from '@/styles/typography';
interface ButtonProp {
width?: string;
background?: string;
color?: Colors;
+ typography?: Typograph;
+ hover?: Colors;
}
const StyledButton = styled.button`
- padding: 15px;
- width: ${({ width }) => width};
- border-radius: 2em;
- display: flex;
- justify-content: center;
- align-items: center;
+ ${layoutMap.styledButton}
+ width: ${({ width = '300px' }) => width};
background: ${({ background = colors.yellow }) => background};
color: ${({ color = 'white' }) => color};
- font-size: 20px;
- font-weight: 700;
+ ${({ typography = 't1' }) => typographyMap[typography]}
+
+ &:hover {
+ background-color: ${({ hover = colors.yellowHover }) => hover};
+ }
`;
export default StyledButton;
diff --git a/src/components/shared/icon/index.tsx b/src/components/shared/icon/index.tsx
index 775ac74..12c2a58 100644
--- a/src/components/shared/icon/index.tsx
+++ b/src/components/shared/icon/index.tsx
@@ -1,10 +1,10 @@
import * as S from './styles';
-export type IconValues =
- | 'logo'
- | 'plus'
- | 'arrow'
- | 'cancel'
+export type IconValues =
+ | 'logo'
+ | 'plus'
+ | 'arrow'
+ | 'cancel'
| 'trophy'
| 'file'
| 'home'
@@ -18,7 +18,11 @@ export type IconValues =
| 'yeslike'
| 'kakao'
| 'google'
- | 'question';
+ | 'question'
+ | 'email'
+ | 'github'
+ | 'blog'
+ | 'settings';
interface IconProps {
value: IconValues;
@@ -75,259 +79,355 @@ const renderIcon = (value: IconValues) => {
/>
);
- case 'trophy':
- return (
-
- );
- case 'file':
- return (
-
+ );
+ case 'settings':
+ return (
+
+
+
+
+ );
}
};
diff --git a/src/hooks/useInfinity.ts b/src/hooks/useInfinity.ts
new file mode 100644
index 0000000..c3a9f7c
--- /dev/null
+++ b/src/hooks/useInfinity.ts
@@ -0,0 +1,19 @@
+import { useInfiniteQuery } from '@tanstack/react-query';
+
+export async function fetchInfiniteData(api: string, pageParam = 1) {
+ const limit = 10; // 한 번에 불러올 데이터 수
+ const response = await fetch(`${api}?page=${pageParam}&limit=${limit}`);
+ const data = await response.json();
+ // 다음 페이지 계산: 'done'이 false면 다음 페이지 번호, true면 undefined
+ const nextPage = data.pageInfo.done ? undefined : pageParam + 1;
+ return { data, nextPage };
+}
+
+export const useGetInfiniteData = (key: string, api: string) => {
+ return useInfiniteQuery({
+ queryKey: [key],
+ queryFn: ({ pageParam = 1 }) => fetchInfiniteData(api, pageParam),
+ initialPageParam: 1,
+ getNextPageParam: (lastPage) => lastPage.nextPage,
+ });
+};
diff --git a/src/pages/mypage/index.tsx b/src/pages/mypage/index.tsx
index 7963ac3..941d360 100644
--- a/src/pages/mypage/index.tsx
+++ b/src/pages/mypage/index.tsx
@@ -1,12 +1,18 @@
import { UserInfo, TabMenu } from '@/components/mypage';
-import { Container } from './styles';
+import * as S from './styles';
+import { MainContainer } from '../main/styles';
+import Nav from '@/components/nav/Nav';
const MyPage = () => {
return (
-
-
-
-
+
+
+
+
+
+
+
+
);
};
diff --git a/src/pages/mypage/styles.ts b/src/pages/mypage/styles.ts
index 2cd24ca..9520816 100644
--- a/src/pages/mypage/styles.ts
+++ b/src/pages/mypage/styles.ts
@@ -2,14 +2,11 @@ import { colors } from '@/styles/colorPalette';
import { layoutMap } from '@/styles/layout';
import styled from '@emotion/styled';
-export const Container = styled.div`
+export const Block = styled.div`
${layoutMap.flexCenter}
- align-items: start;
- margin: 0 420px;
+ flex: 1;
`;
-export const Block = styled.div``;
-
export const Title = styled.div`
font-size: 30px;
font-weight: 700;
@@ -21,3 +18,9 @@ export const Subtitle = styled.div`
font-weight: 400;
margin-top: 15px;
`;
+
+export const Box = styled.div`
+ position: sticky;
+ width: 350px;
+ height: 100%;
+`;
diff --git a/src/pages/post/right/index.tsx b/src/pages/post/right/index.tsx
index d2e5d8a..99874c4 100644
--- a/src/pages/post/right/index.tsx
+++ b/src/pages/post/right/index.tsx
@@ -36,7 +36,7 @@ const PostRight = () => {
}
css={S.testButton}
>
- post
+ Post
);
diff --git a/src/pages/post/right/styles.ts b/src/pages/post/right/styles.ts
index 2cceb7d..e33d8ac 100644
--- a/src/pages/post/right/styles.ts
+++ b/src/pages/post/right/styles.ts
@@ -16,12 +16,6 @@ export const IconCss = css`
`;
export const testButton = css`
- font-size: 24px;
- font-weight: bold;
margin-top: 30px;
align-self: end;
- background-color: ${colors.yellow};
- color: white;
- padding: 10px 50px;
- border-radius: 50px;
`;
diff --git a/src/styles/fonts.ts b/src/styles/fonts.ts
index 9741bf3..92abd70 100644
--- a/src/styles/fonts.ts
+++ b/src/styles/fonts.ts
@@ -16,6 +16,7 @@ export const fontStyles = css`
body {
font-family: 'Pretendard';
- font-size: 18px;
+ font-size: 16px;
+ font-weight: 400;
}
`;
diff --git a/src/styles/layout.ts b/src/styles/layout.ts
index f00a924..a8c9c30 100644
--- a/src/styles/layout.ts
+++ b/src/styles/layout.ts
@@ -19,11 +19,11 @@ export const layoutMap = {
styledButton: css`
padding: 15px;
- width: 100%;
border-radius: 2em;
display: flex;
justify-content: center;
align-items: center;
+ font-weight: 700;
`,
scrollbarsNone: css`
overflow: scroll;
diff --git a/src/styles/typography.ts b/src/styles/typography.ts
index 8f57b7d..d24ed80 100644
--- a/src/styles/typography.ts
+++ b/src/styles/typography.ts
@@ -13,6 +13,13 @@ export const typographyMap = {
t4: css`
font-size: 16px;
`,
+
+ semibold: css`
+ font-weight: 500;
+ `,
+ bold: css`
+ font-weight: 700;
+ `,
};
export type Typograph = keyof typeof typographyMap;