Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PR] 디테일 페이지 애니메이션 적용 및 코드 정리 #55

Merged
merged 11 commits into from
May 14, 2024
Merged
2,323 changes: 400 additions & 1,923 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

21 changes: 12 additions & 9 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import { routers } from './routes';
import Layout from './routes/Layout';
import { Suspense } from 'react';
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Layout />}>
{routers.map(({ path, component }) => (
<Route key={path} path={path} Component={component} />
))}
</Route>
</Routes>
</BrowserRouter>
<Suspense fallback={<>loading</>}>
<BrowserRouter>
<Routes>
<Route path="/" element={<Layout />}>
{routers.map(({ path, component }) => (
<Route key={path} path={path} Component={component} />
))}
</Route>
</Routes>
</BrowserRouter>
</Suspense>
);
}

Expand Down
45 changes: 21 additions & 24 deletions src/apis/post.ts → src/apis/article.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,31 @@
import { ArticleList, ArticleDetail } from '@/types';
import { ArticleDetail, ArticleList } from '@/types';
import instance from './instance';

export const postArticle = async (formData: ArticleDetail) => {
const response = await instance.post('/api/posts', formData);
return response.data;
};

export const getArticle = async (postId: string) => {
const response = await instance.get(`/api/posts/${postId}`);
return response.data as ArticleDetail;
};

interface FetchParams {
pageParam?: number;
size: number;
}

export const getArticles = async ({ pageParam = 1, size }: FetchParams) => {
const response = await instance.get('/api/posts', {
params: {
page: pageParam,
size,
},
});
return response.data as ArticleList;
};

export const postArticle = async (formData: ArticleDetail) => {
const response = await instance.post('/api/posts', formData);
return response.data;
};

export const postCheck = async (
formData: Pick<ArticleDetail, 'language' | 'answer'>,
postId: string,
Expand All @@ -23,21 +38,3 @@ export const postCheck = async (
const response = await instance.post('api/posts/submit', newFormData);
return response.data;
};

interface FetchParams {
pageParam: number;
size: number;
}

export const getArticles = async ({
pageParam = 1,
size,
}: FetchParams) => {
const response = await instance.get(`/api/posts`, {
params: {
size: size,
page: pageParam,
}
});
return response.data as ArticleList;
};
14 changes: 0 additions & 14 deletions src/apis/auth.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/apis/instance.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import axios from 'axios';
import { getNewToken } from './auth';
import { getNewToken } from './refresh';

const instance = axios.create({
baseURL: import.meta.env.VITE_BASE_URL,
Expand Down
6 changes: 2 additions & 4 deletions src/apis/like.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import instance from './instance';

// 좋아요 수 업데이트 구문
const updateLike = async (postId: number): Promise<void> => {
export const postLike = async (postId: number): Promise<void> => {
try {
// console.log(typeof(postId));
const response = await instance.post('/api/like', {postId: postId});
const response = await instance.post('/api/like', { postId: postId });
console.log(response);
} catch (error) {
console.error('실패', error);
throw error;
}
};

export default updateLike;
4 changes: 1 addition & 3 deletions src/components/loader/circleLoader/styles.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import { css } from '@emotion/react';

export const circleStyle = css`
display: block;
width: 3rem;
height: 3rem;
border: 0.5rem solid #e9e9e9;
border-top: 0.5rem solid #3498db;
border-radius: 50%;
position: absolute;
box-sizing: border-box;
left: 50%;
top: 50%;
top: 45%;
`;
8 changes: 1 addition & 7 deletions src/components/main/MainListItem/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { Icon } from '@/components/shared';
import * as S from './styles';
import { ArticleType } from '@/types/index';
import Article from '@/components/shared/article';
import { ArticleType } from '@/types';
import getTimeDifference from '@/utils/getTimeDifference';
import { useEffect } from 'react';

interface ListItemProps {
listItem: ArticleType;
Expand All @@ -12,11 +11,6 @@ interface ListItemProps {
const MainListItem = ({ listItem }: ListItemProps) => {
// 구조 분해 할당으로 author과 그 외 나머지 정보들로 분리
const { user, ...articleDetails } = listItem;

useEffect(() => {
console.log(listItem);
}, []);

const createDate = getTimeDifference(listItem.createdAt);

return (
Expand Down
19 changes: 9 additions & 10 deletions src/components/main/mainList/MainList.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import * as S from './styles';
import { ArticleType } from '@/types/article';
import React from 'react';
import MainListItem from '../mainListItem';
import Loading from '@/components/loader';
import useGetPosts from '@/hooks/post/useGetPosts';
import MainListItem from '../MainListItem';

const MainList = () => {
const { data, ref, isFetchingNextPage } = useGetPosts();
Expand All @@ -14,19 +14,18 @@ const MainList = () => {

return (
<S.MlContainer>
{
data?.pages.map((page, index) => (
<React.Fragment key={index}>
{page.posts.map((item: ArticleType) => (
<MainListItem key={item.postId} listItem={item} />
))}
</React.Fragment>
))}
{data?.pages.map((page, index) => (
<React.Fragment key={index}>
{page.posts.map((item: ArticleType) => (
<MainListItem key={item.postId} listItem={item} />
))}
</React.Fragment>
))}
<div ref={ref} style={{ width: '100%', height: '20px' }}>
{isFetchingNextPage && <Loading />}
</div>
</S.MlContainer>
);
};

export default MainList;
export default MainList;
55 changes: 55 additions & 0 deletions src/components/mypage/liked/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { useInfiniteQuery } from '@tanstack/react-query';
import * as S from '../created/styles';
import { useNickname } from '@/stores/mypage.ts';
import { useEffect, useRef } from 'react';
import { getMypageArticles } from '@/apis/mypage';
import { ArticleType } from '@/types';

const SolvedMenu = () => {
const loginUserId = localStorage.getItem('userId');
const { nickname } = useNickname();
const loader = useRef(null);

const { data, fetchNextPage, hasNextPage, isFetchingNextPage } = useInfiniteQuery({
queryKey: ['liked', nickname, loginUserId],
queryFn: ({ pageParam }) =>
getMypageArticles({
pageIndex: pageParam,
isDone: false,
value: 'liked',
email: nickname,
loginUserId: loginUserId,
}),
initialPageParam: 1,
getNextPageParam: (lastPage) => lastPage.nextPage,
staleTime: 1000 * 60 * 5, // 5분
});

useEffect(() => {
const io = new IntersectionObserver(
(entries) => {
if (entries[0].isIntersecting && hasNextPage) {
fetchNextPage();
}
},
{ threshold: 0.5 },
);
if (loader.current) {
io.observe(loader.current);
}
return () => io.disconnect();
}, [fetchNextPage, hasNextPage, isFetchingNextPage]);

return (
<S.Container>
{data?.pages.map((page) =>
page.data.map((post: ArticleType) => (
<div key={post.postId}>{/* 게시글 공통 컴포넌트로 표시 */}</div>
)),
)}
<div ref={loader} style={{ height: '100px' }} />
</S.Container>
);
};

export default SolvedMenu;
4 changes: 2 additions & 2 deletions src/components/post/posttestCaseBox/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { ChangeEvent, useEffect, useState } from 'react';
import { Icon, Text } from '../../shared';
import { postFormStore } from '@/stores/post';
import { TestCase } from '@/types';

import * as S from './styles';
import { postFormStore } from '@/stores/post';
import { TestCase } from '@/types/post';

const defalutValue = [{ example: '', result: '' }];

Expand Down
16 changes: 13 additions & 3 deletions src/components/shared/StyledButton.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import styled from '@emotion/styled';
import { Colors, colors } from '@/styles/colorPalette';
import { ButtonColor, ButtonSize, buttonColorMap, buttonSizeMap } from '@/styles/button';
import { Colors } from '@/styles/colorPalette';
import {
ButtonColor,
ButtonSize,
buttonActiveMap,
buttonColorMap,
buttonSizeMap,
} from '@/styles/button';

interface ButtonProp {
width?: string;
Expand All @@ -20,7 +26,11 @@ const StyledButton = styled.button<ButtonProp>`
width: ${({ width = '300px' }) => width};

&:hover {
background-color: ${({ hover = colors.yellowHover }) => hover};
${({ buttonType = 'primary' }) => buttonActiveMap[buttonType]}
}
transition: all 0.1s ease;
&:active {
transform: scale(0.95);
}
`;

Expand Down
2 changes: 1 addition & 1 deletion src/components/shared/article/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const Article = ({ article, threedot, statusFlag }: ArticleProps) => {
: formatContent(article.content);

const toHandleDetail = () => {
navigate(`/detail/${article.postNumber}`);
navigate(`/detail/${article.postId}`);
};

return (
Expand Down
Loading