Skip to content

Commit

Permalink
Merge branch 'main' into feat/#543
Browse files Browse the repository at this point in the history
  • Loading branch information
Cyma-s authored Jan 16, 2024
2 parents 358254e + 3745893 commit 1e18d62
Show file tree
Hide file tree
Showing 40 changed files with 602 additions and 315 deletions.
79 changes: 79 additions & 0 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
},
"license": "MIT",
"dependencies": {
"@tanstack/react-query": "^5.14.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.14.1",
Expand All @@ -33,6 +34,7 @@
"@storybook/react": "^7.0.27",
"@storybook/react-webpack5": "^7.0.27",
"@storybook/testing-library": "^0.0.14-next.2",
"@tanstack/react-query-devtools": "^5.14.1",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^14.0.0",
"@testing-library/user-event": "^14.4.3",
Expand All @@ -43,6 +45,7 @@
"@types/styled-components": "^5.1.26",
"@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0",
"axios": "^1.6.1",
"babel-loader": "^9.1.3",
"copy-webpack-plugin": "^11.0.0",
"core-js": "^3.31.1",
Expand Down
16 changes: 16 additions & 0 deletions frontend/src/features/auth/remotes/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { client, clientBasic } from '@/shared/remotes/axios';
import type { AccessTokenRes } from '../types/auth.type';

export const getAccessToken = async (platform: string, code: string) => {
const { data } = await client.get<AccessTokenRes>(`/login/${platform}`, {
params: { code },
});

return data;
};

export const postRefreshAccessToken = async () => {
const { data } = await clientBasic.post<AccessTokenRes>('/reissue');

return data;
};
3 changes: 3 additions & 0 deletions frontend/src/features/auth/types/auth.type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface AccessTokenRes {
accessToken: string;
}
34 changes: 21 additions & 13 deletions frontend/src/features/comments/components/CommentForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,24 @@ import LoginModal from '@/features/auth/components/LoginModal';
import Avatar from '@/shared/components/Avatar';
import useModal from '@/shared/components/Modal/hooks/useModal';
import useToastContext from '@/shared/components/Toast/hooks/useToastContext';
import { useMutation } from '@/shared/hooks/useMutation';
import fetcher from '@/shared/remotes';
import { usePostCommentMutation } from '../queries';

interface CommentFormProps {
getComment: () => Promise<void>;
songId: number;
partId: number;
}

const CommentForm = ({ getComment, songId, partId }: CommentFormProps) => {
const CommentForm = ({ songId, partId }: CommentFormProps) => {
const [newComment, setNewComment] = useState('');
const { isOpen, closeModal: closeLoginModal, openModal: openLoginModal } = useModal();
const { user } = useAuthContext();

const isLoggedIn = !!user;

const { mutateData } = useMutation(() =>
fetcher(`/songs/${songId}/parts/${partId}/comments`, 'POST', { content: newComment.trim() })
);
const {
postNewComment,
mutations: { isPending: isPendingPostComment },
} = usePostCommentMutation();

const { showToast } = useToastContext();

Expand All @@ -35,14 +34,18 @@ const CommentForm = ({ getComment, songId, partId }: CommentFormProps) => {
currentTarget: { value },
}) => setNewComment(value);

const submitNewComment: React.FormEventHandler<HTMLFormElement> = async (event) => {
const submitNewComment: React.FormEventHandler<HTMLFormElement> = (event) => {
event.preventDefault();

await mutateData();

showToast('댓글이 등록되었습니다.');
resetNewComment();
getComment();
postNewComment(
{ songId, partId, content: newComment.trim() },
{
onSuccess: () => {
showToast('댓글이 등록되었습니다.');
resetNewComment();
},
}
);
};

return (
Expand All @@ -53,6 +56,7 @@ const CommentForm = ({ getComment, songId, partId }: CommentFormProps) => {
<Avatar src={shookshook} alt="슉슉이" />
<Input
type="text"
disabled={isPendingPostComment}
value={newComment}
onChange={changeNewComment}
placeholder="댓글 추가..."
Expand Down Expand Up @@ -123,6 +127,10 @@ const Input = styled.input`
outline: none;
-webkit-box-shadow: none;
box-shadow: none;
&:disabled {
color: ${({ theme: { color } }) => color.disabledBackground};
}
`;

const FlexEnd = styled.div`
Expand Down
21 changes: 3 additions & 18 deletions frontend/src/features/comments/components/CommentList.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,21 @@
import { useEffect } from 'react';
import { styled } from 'styled-components';
import cancelIcon from '@/assets/icon/cancel.svg';
import BottomSheet from '@/shared/components/BottomSheet/BottomSheet';
import useModal from '@/shared/components/Modal/hooks/useModal';
import Spacing from '@/shared/components/Spacing';
import SRHeading from '@/shared/components/SRHeading';
import useFetch from '@/shared/hooks/useFetch';
import fetcher from '@/shared/remotes';
import { useCommentsQuery } from '../queries';
import Comment from './Comment';
import CommentForm from './CommentForm';

interface Comment {
id: number;
content: string;
createdAt: string;
writerNickname: string;
}

interface CommentListProps {
songId: number;
partId: number;
}

const CommentList = ({ songId, partId }: CommentListProps) => {
const { isOpen, openModal, closeModal } = useModal(false);
const { data: comments, fetchData: getComment } = useFetch<Comment[]>(() =>
fetcher(`/songs/${songId}/parts/${partId}/comments`, 'GET')
);

useEffect(() => {
getComment();
}, [partId]);
const { comments } = useCommentsQuery(songId, partId);

if (!comments) {
return null;
Expand Down Expand Up @@ -73,7 +58,7 @@ const CommentList = ({ songId, partId }: CommentListProps) => {
))}
</Comments>
<Spacing direction="vertical" size={8} />
<CommentForm getComment={getComment} songId={songId} partId={partId} />
<CommentForm songId={songId} partId={partId} />
</BottomSheet>
</>
);
Expand Down
24 changes: 24 additions & 0 deletions frontend/src/features/comments/queries/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { getComments, postComment } from '../remotes/comments';

export const useCommentsQuery = (songId: number, partId: number) => {
const { data: comments, ...queries } = useQuery({
queryKey: ['comments', songId, partId],
queryFn: () => getComments(songId, partId),
});

return { comments, queries };
};

export const usePostCommentMutation = () => {
const client = useQueryClient();

const { mutate: postNewComment, ...mutations } = useMutation({
mutationFn: postComment,
onSuccess: (_, { songId, partId }) => {
client.invalidateQueries({ queryKey: ['comments', songId, partId] });
},
});

return { postNewComment, mutations };
};
20 changes: 20 additions & 0 deletions frontend/src/features/comments/remotes/comments.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { client } from '@/shared/remotes/axios';
import type { Comment } from '../types/comment.type';

export const postComment = async ({
songId,
partId,
content,
}: {
songId: number;
partId: number;
content: string;
}) => {
await client.post(`/songs/${songId}/parts/${partId}/comments`, { content });
};

export const getComments = async (songId: number, partId: number) => {
const { data } = await client.get<Comment[]>(`/songs/${songId}/parts/${partId}/comments`);

return data;
};
6 changes: 6 additions & 0 deletions frontend/src/features/comments/types/comment.type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export interface Comment {
id: number;
content: string;
createdAt: string;
writerNickname: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@ import { useNavigate } from 'react-router-dom';
import styled from 'styled-components';
import { useAuthContext } from '@/features/auth/components/AuthProvider';
import useCollectingPartContext from '@/features/killingParts/hooks/useCollectingPartContext';
import { usePostKillingPart } from '@/features/killingParts/remotes/usePostKillingPart';
import useVideoPlayerContext from '@/features/youtube/hooks/useVideoPlayerContext';
import useModal from '@/shared/components/Modal/hooks/useModal';
import Modal from '@/shared/components/Modal/Modal';
import Spacing from '@/shared/components/Spacing';
import { useMutation } from '@/shared/hooks/useMutation';
import { toPlayingTimeText } from '@/shared/utils/convertTime';
import { postKillingPart } from '../remotes/killingPart';

const RegisterPart = () => {
const { isOpen, openModal, closeModal } = useModal();
const { user } = useAuthContext();
const { interval, partStartTime, songId } = useCollectingPartContext();
const video = useVideoPlayerContext();
const { createKillingPart } = usePostKillingPart();
const { mutateData: createKillingPart } = useMutation(postKillingPart);
const navigate = useNavigate();

// 현재 useMutation 훅이 response 객체를 리턴하지 않고 내부적으로 처리합니다.
Expand Down
6 changes: 0 additions & 6 deletions frontend/src/features/killingParts/hooks/killingPart.ts

This file was deleted.

18 changes: 18 additions & 0 deletions frontend/src/features/killingParts/remotes/killingPart.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { client } from '@/shared/remotes/axios';
import type { KillingPartPostRequest } from '@/shared/types/killingPart';
import type { SongInfo } from '@/shared/types/song';

// PartCollectingPage에 존재하던 remote 함수입니다.
// useFetch<SongInfo>(() => fetcher(`/songs/${songId}`, 'GET')) 로직에서 분리하였습니다.
// SongInfo type에는 killingPart[] 필드가 있는데, 마이파트 수집용 `노래 1개` 조회에서 해당 타입이 사용되고 있습니다.
// 추후 수정되어야 합니다.

export const getSong = async (songId: number) => {
const { data } = await client.get<SongInfo>(`/songs/${songId}`);

return data;
};

export const postKillingPart = async (songId: number, body: KillingPartPostRequest) => {
await client.post(`/songs/${songId}/member-parts`, body);
};

This file was deleted.

Loading

0 comments on commit 1e18d62

Please sign in to comment.