Skip to content

Commit e4c4ab5

Browse files
authored
리팩토링 v1.2.1
리팩토링 v1.2.1
2 parents ddc77ee + 4962ec4 commit e4c4ab5

17 files changed

Lines changed: 496 additions & 310 deletions

File tree

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
"start:json-server": "json-server --watch db.json --port 5000"
1313
},
1414
"dependencies": {
15+
"@tanstack/react-query": "^5.70.0",
16+
"@tanstack/react-query-devtools": "^5.70.0",
1517
"@types/styled-components": "^5.1.34",
1618
"axios": "^1.7.2",
1719
"dayjs": "^1.11.12",

src/apis/post/index.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { useQuery } from '@tanstack/react-query';
2+
13
import { newRequest } from '@apis/core';
24

35
import type { EmptySuccessResponse } from '@apis/core/dto';
@@ -17,8 +19,15 @@ export const createPostApi = (data: CreatePostRequest) => newRequest.post<Create
1719

1820
// 게시글 리스트 조회
1921
// 전체 게시글 리스트
20-
export const getPostListApi = (page: number = 1, take: number = 10) =>
21-
newRequest.get<GetPostListResponse>(`/post`, { params: { page, take } });
22+
export const getPostListApi = async ({ pageParam = 1 }) => {
23+
const response = await newRequest.get<GetPostListResponse>('/post', {
24+
params: { page: pageParam, take: 10 },
25+
});
26+
return {
27+
posts: response.data.post,
28+
nextPage: response.data.post.length > 0 ? pageParam + 1 : undefined, // 다음 페이지 여부 확인
29+
};
30+
};
2231
// 유저 게시글 리스트
2332
export const getUserPostListApi = (page: number = 1, take: number = 10, userId: number) =>
2433
newRequest.get<GetUserPostListResponse>(`/post`, { params: { page, take, userId } });
@@ -36,3 +45,11 @@ export const deletePostApi = (postId: number) => newRequest.delete<EmptySuccessR
3645
// 대표 게시글 지정
3746
export const modifyPostRepresentativeStatusApi = (postId: number) =>
3847
newRequest.patch<EmptySuccessResponse>(`/post/${postId}/is-representative`);
48+
49+
export const usePostDetail = (postId: number) => {
50+
return useQuery({
51+
queryKey: ['postDetail', postId],
52+
queryFn: () => getPostDetailApi(postId),
53+
enabled: !!postId, // postId가 존재할 때만 요청 수행
54+
});
55+
};

src/components/Skeleton/index.tsx

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { SkeletonContainer } from './styles';
2+
3+
interface SkeletonProps {
4+
width?: string | number;
5+
height?: string | number;
6+
borderRadius?: string | number;
7+
className?: string;
8+
style?: React.CSSProperties;
9+
}
10+
11+
const Skeleton: React.FC<SkeletonProps> = ({
12+
width = '100%',
13+
height = '16px',
14+
borderRadius = '5px',
15+
className = '',
16+
}) => {
17+
// width와 height가 숫자인 경우 rem 단위를 추가
18+
const getSize = (size: string | number) => {
19+
if (typeof size === 'number') {
20+
return `${size}rem`;
21+
}
22+
return size;
23+
};
24+
25+
return (
26+
<SkeletonContainer
27+
className={className}
28+
style={{
29+
width: getSize(width),
30+
height: getSize(height),
31+
borderRadius: getSize(borderRadius),
32+
}}
33+
/>
34+
);
35+
};
36+
37+
export default Skeleton;

src/components/Skeleton/styles.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { styled } from 'styled-components';
2+
3+
export const SkeletonContainer = styled.div`
4+
background-color: #e0e0e0;
5+
position: relative;
6+
overflow: hidden;
7+
background: linear-gradient(90deg, #e0e0e0 0%, #f0f0f0 50%, #e0e0e0 100%);
8+
background-size: 200% 100%;
9+
animation: shimmer 1.5s infinite;
10+
11+
@keyframes shimmer {
12+
0% {
13+
background-position: 200% 0;
14+
}
15+
100% {
16+
background-position: -200% 0;
17+
}
18+
}
19+
`;

src/main.tsx

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
2+
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
13
import { createRoot } from 'react-dom/client';
24
import { RecoilRoot } from 'recoil';
35
import { ThemeProvider } from 'styled-components';
@@ -10,13 +12,18 @@ import { SocketProvider } from '@context/SocketProvider';
1012

1113
import App from './App';
1214

15+
const queryClient = new QueryClient();
16+
1317
createRoot(document.getElementById('root')!).render(
1418
<ThemeProvider theme={theme}>
15-
<GlobalStyle />
16-
<RecoilRoot>
17-
<SocketProvider>
18-
<App />
19-
</SocketProvider>
20-
</RecoilRoot>
19+
<QueryClientProvider client={queryClient}>
20+
<GlobalStyle />
21+
<RecoilRoot>
22+
<SocketProvider>
23+
<App />
24+
<ReactQueryDevtools initialIsOpen={false} />
25+
</SocketProvider>
26+
</RecoilRoot>
27+
</QueryClientProvider>
2128
</ThemeProvider>,
2229
);

src/pages/Account/AccountCancel/index.tsx

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useState } from 'react';
1+
import { useState, useEffect } from 'react';
22
import { useNavigate } from 'react-router-dom';
33

44
import theme from '@styles/theme';
@@ -11,6 +11,7 @@ import back from '@assets/arrow/left.svg';
1111
import BottomButton from '@components/BottomButton/index';
1212
import { OODDFrame } from '@components/Frame/Frame';
1313
import Modal from '@components/Modal/index';
14+
import Skeleton from '@components/Skeleton';
1415
import { StyledText } from '@components/Text/StyledText';
1516
import TopBar from '@components/TopBar/index';
1617

@@ -30,8 +31,15 @@ const AccountCancel: React.FC = () => {
3031
const [isChecked, setIsChecked] = useState(false);
3132
const [modalContent, setModalContent] = useState<string | null>(null);
3233
const [isModalVisible, setIsModalVisible] = useState<boolean>(false);
34+
const [isLoading, setIsLoading] = useState(true); // Loading state
3335
const navigate = useNavigate();
3436

37+
useEffect(() => {
38+
setTimeout(() => {
39+
setIsLoading(false);
40+
}, 1000);
41+
}, []);
42+
3543
const handleCheckboxChange = () => {
3644
setIsChecked(!isChecked);
3745
};
@@ -79,6 +87,23 @@ const AccountCancel: React.FC = () => {
7987
}
8088
};
8189

90+
if (isLoading) {
91+
return (
92+
<OODDFrame>
93+
<CancelContainer>
94+
<TopBar text="회원 탈퇴" LeftButtonSrc={back} onClickLeftButton={() => navigate(-1)} />
95+
<SubTitle>
96+
<StyledText as="div" $textTheme={{ style: 'headline2-medium' }} color={theme.colors.text.primary}>
97+
OOTD 탈퇴 전 확인하세요!
98+
<Skeleton width="100%" height={25} />
99+
</StyledText>
100+
</SubTitle>
101+
</CancelContainer>
102+
<BottomButton content="탈퇴하기" onClick={handleDeleteAccount} disabled={!isChecked} />
103+
</OODDFrame>
104+
);
105+
}
106+
82107
return (
83108
<OODDFrame>
84109
<CancelContainer>

src/pages/Account/AccountSetting/index.tsx

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ import leave from '@assets/default/leave.svg';
1212
import Profile_s from '@assets/default/my-page.svg';
1313

1414
import { OODDFrame } from '@components/Frame/Frame';
15-
import Loading from '@components/Loading/index';
1615
import Modal from '@components/Modal';
16+
import Skeleton from '@components/Skeleton';
1717
import { StyledText } from '@components/Text/StyledText';
1818
import TopBar from '@components/TopBar/index';
1919

@@ -44,8 +44,7 @@ const AccountSetting: React.FC = () => {
4444
setIsLoading(false);
4545
}
4646
};
47-
48-
getUserInfo();
47+
setTimeout(getUserInfo, 1000);
4948
}, []);
5049

5150
const handleConfirmLogout = () => {
@@ -68,7 +67,33 @@ const AccountSetting: React.FC = () => {
6867
};
6968

7069
if (isLoading) {
71-
return <Loading />;
70+
return (
71+
<OODDFrame>
72+
<ProfileEditContainer>
73+
<TopBar text="계정 관리" LeftButtonSrc={back} onClickLeftButton={() => navigate(-1)} />
74+
<ProfilePicWrapper>
75+
<ProfilePic>
76+
<Skeleton width={7.5} height={7.5} borderRadius={5} />
77+
</ProfilePic>{' '}
78+
<Row>
79+
<Skeleton width="60%" height={1.25} />
80+
</Row>
81+
<Row>
82+
<Skeleton width="100%" height={1.25} />
83+
</Row>
84+
</ProfilePicWrapper>
85+
86+
<List>
87+
<ListItem>
88+
<Skeleton width="100%" height={2.5} />
89+
</ListItem>
90+
<ListItem>
91+
<Skeleton width="100%" height={2.5} />
92+
</ListItem>
93+
</List>
94+
</ProfileEditContainer>
95+
</OODDFrame>
96+
);
7297
}
7398

7499
return (

src/pages/Account/AccountSetting/styles.tsx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ export const ProfilePicWrapper = styled.div`
1313
display: flex;
1414
flex-direction: column;
1515
align-items: center;
16-
margin-bottom: 1.25rem;
17-
margin-top: 1.5rem;
1816
`;
1917

2018
export const ProfilePic = styled.div`
@@ -24,7 +22,6 @@ export const ProfilePic = styled.div`
2422
border-radius: 50%;
2523
overflow: hidden;
2624
margin-top: 2.125rem;
27-
margin-bottom: 1.375rem;
2825
2926
img {
3027
width: 100%;
@@ -42,7 +39,7 @@ export const Row = styled.div`
4239
justify-content: center;
4340
align-items: center;
4441
width: 100%;
45-
margin-bottom: 0.625rem;
42+
margin-top: 10px;
4643
4744
${Label} {
4845
width: auto;
@@ -67,7 +64,8 @@ export const List = styled.ul`
6764
export const ListItem = styled.li`
6865
display: flex;
6966
align-items: center;
70-
padding: 0.9375rem 1.25rem;
67+
padding: 15px 10px;
68+
7169
border-bottom: 0px solid ${({ theme }) => theme.colors.background.divider};
7270
cursor: pointer;
7371

0 commit comments

Comments
 (0)