diff --git a/frontend/src/components/Common/DiaryListItem.tsx b/frontend/src/components/Common/DiaryListItem.tsx index b1f1119..e9dfcb7 100644 --- a/frontend/src/components/Common/DiaryListItem.tsx +++ b/frontend/src/components/Common/DiaryListItem.tsx @@ -1,10 +1,7 @@ import { useState, useEffect } from 'react'; -import { useMutation, useQueryClient } from '@tanstack/react-query'; import { useNavigate } from 'react-router-dom'; import EmojiPicker from 'emoji-picker-react'; -import { postReaction, deleteReaction } from '@api/Reaction'; - import { IDiaryContent } from '@type/components/Common/DiaryList'; import Reaction from '@components/Common/Reaction'; @@ -13,7 +10,8 @@ import ReactionList from '@components/Diary/ReactionList'; import Keyword from '@components/Common/Keyword'; import useModal from '@hooks/useModal'; -import { useToast } from '@/hooks/useToast'; +import usePostReactionMutation from '@hooks/usePostReactionMutation'; +import useDeleteReactionMutation from '@hooks/useDeleteReactionMutation'; import { FEED, PAGE_URL } from '@util/constants'; import { formatDateString } from '@util/funcs'; @@ -24,44 +22,30 @@ interface DiaryListItemProps { } const DiaryListItem = ({ pageType, diaryItem }: DiaryListItemProps) => { - const queryClient = useQueryClient(); const navigate = useNavigate(); - const openToast = useToast(); const [showEmojiPicker, setShowEmojiPicker] = useState(false); const [selectedEmoji, setSelectedEmoji] = useState(''); const [totalReaction, setTotalReaction] = useState(0); const { isOpen, openModal } = useModal(); + const userId = localStorage.getItem('userId') as string; + useEffect(() => { setSelectedEmoji(diaryItem.leavedReaction); setTotalReaction(diaryItem.reactionCount); }, [diaryItem]); - const postReactionMutation = useMutation({ - mutationFn: () => postReaction(Number(diaryItem.diaryId), selectedEmoji), - onSuccess: () => { - queryClient.removeQueries({ - queryKey: ['dayDiaryList', localStorage.getItem('userId')], - }); - queryClient.removeQueries({ - queryKey: ['myDayDiaryList', localStorage.getItem('userId')], - }); - openToast('공감을 남겼습니다!'); - }, - }); - - const deleteReactionMutation = useMutation({ - mutationFn: () => deleteReaction(Number(diaryItem.diaryId), selectedEmoji), - onSuccess: () => { - queryClient.removeQueries({ - queryKey: ['dayDiaryList', localStorage.getItem('userId')], - }); - queryClient.removeQueries({ - queryKey: ['myDayDiaryList', localStorage.getItem('userId')], - }); - openToast('공감을 취소했습니다!'); - }, - }); + const postReactionMutation = usePostReactionMutation( + Number(userId), + Number(diaryItem.diaryId), + selectedEmoji, + ); + + const deleteReactionMutation = useDeleteReactionMutation( + Number(userId), + Number(diaryItem.diaryId), + selectedEmoji, + ); const handleDeleteReaction = async () => { await deleteReactionMutation.mutate(); diff --git a/frontend/src/components/Detail/DiaryContent.tsx b/frontend/src/components/Detail/DiaryContent.tsx index 96fdc8c..9e09f2c 100644 --- a/frontend/src/components/Detail/DiaryContent.tsx +++ b/frontend/src/components/Detail/DiaryContent.tsx @@ -1,10 +1,7 @@ import { useState, useEffect } from 'react'; -import { useMutation, useQueryClient } from '@tanstack/react-query'; import EmojiPicker from 'emoji-picker-react'; import Parser from 'html-react-parser'; -import { postReaction, deleteReaction } from '@api/Reaction'; - import { IReactionedFriends } from '@type/components/Common/ReactionList'; import ProfileItem from '@components/Common/ProfileItem'; @@ -13,8 +10,9 @@ import Keyword from '@components/Common/Keyword'; import ReactionList from '@components/Diary/ReactionList'; import useModal from '@hooks/useModal'; -import { useToast } from '@hooks/useToast'; import useReactionListQuery from '@hooks/useReactionListQuery'; +import usePostReactionMutation from '@hooks/usePostReactionMutation'; +import useDeleteReactionMutation from '@hooks/useDeleteReactionMutation'; import { formatDateString } from '@util/funcs'; @@ -45,8 +43,6 @@ const DiaryContent = ({ const [selectedEmoji, setSelectedEmoji] = useState(''); const [totalReaction, setTotalReaction] = useState(reactionCount); const { openModal } = useModal(); - const openToast = useToast(); - const queryClient = useQueryClient(); const { data, isError, isSuccess } = useReactionListQuery(diaryId); @@ -54,31 +50,9 @@ const DiaryContent = ({ return

Error fetching data

; } - const postReactionMutation = useMutation({ - mutationFn: () => postReaction(diaryId, selectedEmoji), - onSuccess: () => { - queryClient.removeQueries({ - queryKey: ['dayDiaryList', localStorage.getItem('userId')], - }); - queryClient.removeQueries({ - queryKey: ['myDayDiaryList', localStorage.getItem('userId')], - }); - openToast('공감을 남겼습니다!'); - }, - }); - - const deleteReactionMutation = useMutation({ - mutationFn: () => deleteReaction(diaryId, selectedEmoji), - onSuccess: () => { - queryClient.removeQueries({ - queryKey: ['dayDiaryList', localStorage.getItem('userId')], - }); - queryClient.removeQueries({ - queryKey: ['myDayDiaryList', localStorage.getItem('userId')], - }); - openToast('공감을 취소했습니다!'); - }, - }); + const postReactionMutation = usePostReactionMutation(userId, diaryId, selectedEmoji); + + const deleteReactionMutation = useDeleteReactionMutation(userId, diaryId, selectedEmoji); const handleDeleteReaction = async () => { await deleteReactionMutation.mutate(); diff --git a/frontend/src/components/Edit/KeywordBox.tsx b/frontend/src/components/Edit/KeywordBox.tsx index ef0b538..3dda0f3 100644 --- a/frontend/src/components/Edit/KeywordBox.tsx +++ b/frontend/src/components/Edit/KeywordBox.tsx @@ -1,8 +1,5 @@ import { useState } from 'react'; -import { useNavigate, useLocation } from 'react-router-dom'; -import { useMutation, useQueryClient } from '@tanstack/react-query'; - -import { createDiary, updateDiary } from '@api/Edit'; +import { useLocation } from 'react-router-dom'; import Loading from '@components/Common/Loading'; import Keyword from '@components/Common/Keyword'; @@ -10,8 +7,8 @@ import Keyword from '@components/Common/Keyword'; import useEditStore from '@store/useEditStore'; import { useToast } from '@hooks/useToast'; - -import { PAGE_URL } from '@util/constants'; +import useCreateDiaryMutation from '@hooks/useCreateDiaryMutation'; +import useUpdateDiaryMutation from '@hooks/useUpdateDiaryMutation'; interface CreateDiaryParams { title: string; @@ -23,10 +20,9 @@ interface CreateDiaryParams { } const KeywordBox = () => { - const queryClient = useQueryClient(); const openToast = useToast(); - const navigate = useNavigate(); + const userId = localStorage.getItem('userid') as string; const { state } = useLocation(); const [keyword, setKeyword] = useState(''); const { diaryId, title, content, emoji, status, thumbnail, keywordList, setKeywordList } = @@ -41,49 +37,9 @@ const KeywordBox = () => { thumbnail, }; - const createDiaryMutation = useMutation({ - mutationFn: (params: CreateDiaryParams) => createDiary(params), - onSuccess: () => { - navigate(PAGE_URL.MY_DIARY); - queryClient.invalidateQueries({ - queryKey: ['grass', localStorage.getItem('userId')], - refetchType: 'all', - }); - queryClient.invalidateQueries({ - queryKey: ['emotionStat', localStorage.getItem('userId')], - refetchType: 'all', - }); - queryClient.removeQueries({ - queryKey: ['dayDiaryList', localStorage.getItem('userId')], - }); - queryClient.removeQueries({ - queryKey: ['myDayDiaryList', localStorage.getItem('userId')], - }); - openToast('일기가 작성되었습니다!'); - }, - }); - - const updateDiaryMutation = useMutation({ - mutationFn: (params: CreateDiaryParams) => updateDiary(params, diaryId), - onSuccess: () => { - navigate(`${PAGE_URL.DETAIL}/${diaryId}`); - queryClient.invalidateQueries({ - queryKey: ['grass', localStorage.getItem('userId')], - refetchType: 'all', - }); - queryClient.invalidateQueries({ - queryKey: ['emotionStat', localStorage.getItem('userId')], - refetchType: 'all', - }); - queryClient.removeQueries({ - queryKey: ['dayDiaryList', localStorage.getItem('userId')], - }); - queryClient.removeQueries({ - queryKey: ['myDayDiaryList', localStorage.getItem('userId')], - }); - openToast('일기가 수정되었습니다!'); - }, - }); + const createDiaryMutation = useCreateDiaryMutation(userId); + + const updateDiaryMutation = useUpdateDiaryMutation(userId, diaryId); const onSubmit = () => { if (!title || title.trim() === '' || !content || content.trim() === '') { diff --git a/frontend/src/components/Home/FriendModalItem.tsx b/frontend/src/components/Home/FriendModalItem.tsx index 65144b0..e4255d4 100644 --- a/frontend/src/components/Home/FriendModalItem.tsx +++ b/frontend/src/components/Home/FriendModalItem.tsx @@ -1,9 +1,10 @@ import { useNavigate } from 'react-router-dom'; -import { useMutation, useQueryClient } from '@tanstack/react-query'; +import { useQueryClient } from '@tanstack/react-query'; -import { cancelRequestFriend, deleteFriend, allowFriend, rejectFriend } from '@api/FriendModal'; - -import { useToast } from '@hooks/useToast'; +import useCancelRequestMutation from '@hooks/useCancelRequestMutation'; +import useDeleteFriendMutation from '@hooks/useDeleteFriendMutation'; +import useAllowFriendMutation from '@hooks/useAllowFriendMutation'; +import useRejectFriendMutation from '@hooks/useRejectFriendMutation'; import { PROFILE_BUTTON_TYPE, PAGE_URL, reactQueryKeys } from '@util/constants'; @@ -15,12 +16,9 @@ interface FriendModalItemProps { type: string; } -const DB_WAITING_TIME = 100; - const FriendModalItem = ({ email, profileImage, nickname, id, type }: FriendModalItemProps) => { const navigate = useNavigate(); const queryClient = useQueryClient(); - const openToast = useToast(); const goFriendHome = () => { navigate(`${PAGE_URL.HOME}${id}`); @@ -29,55 +27,13 @@ const FriendModalItem = ({ email, profileImage, nickname, id, type }: FriendModa }); }; - const cancelRequestMutation = useMutation({ - mutationFn: (receiverId: number) => cancelRequestFriend(receiverId), - onSuccess() { - openToast('친구 신청을 취소했습니다.'); - setTimeout(() => { - queryClient.invalidateQueries({ - queryKey: [reactQueryKeys.SendList], - }); - }, DB_WAITING_TIME); - }, - }); + const cancelRequestMutation = useCancelRequestMutation(); - const deleteFriendMutation = useMutation({ - mutationFn: (friendId: number) => deleteFriend(friendId), - onSuccess() { - openToast('친구가 삭제되었습니다.'); - queryClient.invalidateQueries({ - queryKey: [reactQueryKeys.FriendList], - }); - queryClient.invalidateQueries({ - queryKey: [reactQueryKeys.ProfileData], - }); - }, - }); + const deleteFriendMutation = useDeleteFriendMutation(); - const allowFriendMutation = useMutation({ - mutationFn: (senderId: number) => allowFriend(senderId), - onSuccess() { - openToast('친구 요청을 수락하였습니다.'); - queryClient.invalidateQueries({ - queryKey: [reactQueryKeys.ReceivedList], - }); - queryClient.invalidateQueries({ - queryKey: [reactQueryKeys.ProfileData], - }); - }, - }); + const allowFriendMutation = useAllowFriendMutation(); - const rejectFriendMutation = useMutation({ - mutationFn: (senderId: number) => rejectFriend(senderId), - onSuccess() { - openToast('친구 요청을 거절하였습니다.'); - setTimeout(() => { - queryClient.invalidateQueries({ - queryKey: [reactQueryKeys.ReceivedList], - }); - }, DB_WAITING_TIME); - }, - }); + const rejectFriendMutation = useRejectFriendMutation(); const getButtonElement = (type: string) => { switch (type) { diff --git a/frontend/src/components/Home/Profile.tsx b/frontend/src/components/Home/Profile.tsx index 0314989..5d35162 100644 --- a/frontend/src/components/Home/Profile.tsx +++ b/frontend/src/components/Home/Profile.tsx @@ -1,13 +1,14 @@ import { useNavigate, useParams } from 'react-router-dom'; -import { useMutation, useQueryClient } from '@tanstack/react-query'; - -import { deleteFriend, requestFriend } from '@api/FriendModal'; import Button from '@components/Common/Button'; import FriendList from '@components/Home/FriendList'; import FriendRequest from '@components/Home/FriendRequest'; import ProfileEdit from '@components/Home/ProfileEdit'; +import useModal from '@hooks/useModal'; +import useRequestFriendMutation from '@hooks/useRequestFriendMutation'; +import useDeleteFriendMutation from '@hooks/useDeleteFriendMutation'; + import { DEFAULT, GREET_MESSAGES, @@ -15,12 +16,8 @@ import { TEXT_ABOUT_EXISTED_TODAY, LARGE, PAGE_URL, - reactQueryKeys, } from '@util/constants'; -import { useToast } from '@hooks/useToast'; -import useModal from '@hooks/useModal'; - interface ProfileProps { userId: number; userData: ProfileData; @@ -42,8 +39,6 @@ interface relationData { const Profile = ({ userId, userData }: ProfileProps) => { const navigate = useNavigate(); - const queryClient = useQueryClient(); - const openToast = useToast(); const loginUserId = localStorage.getItem('userId'); const paramsUserId = useParams().userId ?? false; @@ -68,33 +63,9 @@ const Profile = ({ userId, userData }: ProfileProps) => { const getRandomIndex = Math.floor(Math.random() * GREET_MESSAGES.length); - const requestFriendMutation = useMutation({ - mutationFn: (receiverId: number) => requestFriend(receiverId), - onSuccess() { - openToast('친구 요청을 보냈습니다.'); - setTimeout(() => { - queryClient.invalidateQueries({ - queryKey: [reactQueryKeys.SendList], - }); - queryClient.invalidateQueries({ - queryKey: [reactQueryKeys.ProfileData], - }); - }, 100); - }, - }); - - const deleteFriendMutation = useMutation({ - mutationFn: (friendId: number) => deleteFriend(friendId), - onSuccess() { - openToast('친구 삭제가 완료되었습니다.'); - queryClient.invalidateQueries({ - queryKey: [reactQueryKeys.FriendList], - }); - queryClient.invalidateQueries({ - queryKey: [reactQueryKeys.ProfileData], - }); - }, - }); + const requestFriendMutation = useRequestFriendMutation(); + + const deleteFriendMutation = useDeleteFriendMutation(); const getRelationContent = () => { if (relation === null) { diff --git a/frontend/src/components/Home/ProfileEdit.tsx b/frontend/src/components/Home/ProfileEdit.tsx index a44f3bb..42ef5d9 100644 --- a/frontend/src/components/Home/ProfileEdit.tsx +++ b/frontend/src/components/Home/ProfileEdit.tsx @@ -1,9 +1,6 @@ import { useRef, useState } from 'react'; -import { useMutation, useQueryClient } from '@tanstack/react-query'; -import { updateProfile } from '@api/FriendModal'; - -import { useToast } from '@hooks/useToast'; +import useUpdateProfileMutation from '@hooks/useUpdateProfileMutation'; interface ProfileEditProps { profileImage: string; @@ -11,27 +8,14 @@ interface ProfileEditProps { } const ProfileEdit = ({ profileImage, nickname }: ProfileEditProps) => { - const queryClient = useQueryClient(); - const openToast = useToast(); - const userId = localStorage.getItem('userId'); + const userId = localStorage.getItem('userId') as string; const [newNickname, setNewNickname] = useState(''); const [imageSrc, setImageSrc] = useState(profileImage); const [newProfileImage, setNewProfileImage] = useState(); const fileInputRef = useRef(null); - const updateMutation = useMutation({ - mutationFn: (formData: FormData) => updateProfile(formData), - onSuccess() { - queryClient.invalidateQueries({ - queryKey: ['profileData', userId], - }); - openToast('프로필 정보가 수정되었습니다.'); - }, - onError() { - openToast('사진의 크기는 최대 10MB입니다.'); - }, - }); + const updateMutation = useUpdateProfileMutation(userId); const onChangeNickname = (e: React.ChangeEvent) => { setNewNickname(e.target.value); diff --git a/frontend/src/components/MyDiary/Card.tsx b/frontend/src/components/MyDiary/Card.tsx index 1c63790..a54971d 100644 --- a/frontend/src/components/MyDiary/Card.tsx +++ b/frontend/src/components/MyDiary/Card.tsx @@ -1,10 +1,7 @@ import { useState } from 'react'; -import { useMutation, useQueryClient } from '@tanstack/react-query'; import { useNavigate } from 'react-router-dom'; import EmojiPicker from 'emoji-picker-react'; -import { postReaction, deleteReaction } from '@api/Reaction'; - import { IDiaryContent } from '@type/components/Common/DiaryList'; import Keyword from '@components/Common/Keyword'; @@ -12,6 +9,8 @@ import Reaction from '@components/Common/Reaction'; import ReactionList from '@components/Diary/ReactionList'; import useModal from '@hooks/useModal'; +import usePostReactionMutation from '@hooks/usePostReactionMutation'; +import useDeleteReactionMutation from '@hooks/useDeleteReactionMutation'; import { formatDateString } from '@util/funcs'; import { PAGE_URL, SMALL } from '@util/constants'; @@ -23,32 +22,25 @@ interface CardProps { } const Card = ({ diaryItem, styles, size }: CardProps) => { - const queryClient = useQueryClient(); const navigate = useNavigate(); const [showEmojiPicker, setShowEmojiPicker] = useState(false); const [selectedEmoji, setSelectedEmoji] = useState(diaryItem.leavedReaction); const [totalReaction, setTotalReaction] = useState(diaryItem.reactionCount); const { openModal } = useModal(); - const postReactionMutation = useMutation({ - mutationFn: () => postReaction(Number(diaryItem.diaryId), selectedEmoji), - onSuccess: () => { - queryClient.invalidateQueries({ - queryKey: ['reactionList', diaryItem.diaryId], - refetchType: 'active', - }); - }, - }); + const userId = localStorage.getItem('userId') as string; + + const postReactionMutation = usePostReactionMutation( + Number(userId), + Number(diaryItem.diaryId), + selectedEmoji, + ); - const deleteReactionMutation = useMutation({ - mutationFn: () => deleteReaction(Number(diaryItem.diaryId), selectedEmoji), - onSuccess: () => { - queryClient.invalidateQueries({ - queryKey: ['reactionList', diaryItem.diaryId], - refetchType: 'active', - }); - }, - }); + const deleteReactionMutation = useDeleteReactionMutation( + Number(userId), + Number(diaryItem.diaryId), + selectedEmoji, + ); const handleDeleteReaction = async () => { await deleteReactionMutation.mutate(); diff --git a/frontend/src/hooks/useAllowFriendMutation.ts b/frontend/src/hooks/useAllowFriendMutation.ts new file mode 100644 index 0000000..b875bb5 --- /dev/null +++ b/frontend/src/hooks/useAllowFriendMutation.ts @@ -0,0 +1,27 @@ +import { useMutation, useQueryClient } from '@tanstack/react-query'; + +import { allowFriend } from '@api/FriendModal'; + +import { useToast } from '@hooks/useToast'; + +import { reactQueryKeys } from '@util/constants'; + +const useAllowFriendMutation = () => { + const queryClient = useQueryClient(); + const openToast = useToast(); + + return useMutation({ + mutationFn: (senderId: number) => allowFriend(senderId), + onSuccess() { + openToast('친구 요청을 수락하였습니다.'); + queryClient.invalidateQueries({ + queryKey: [reactQueryKeys.ReceivedList], + }); + queryClient.invalidateQueries({ + queryKey: [reactQueryKeys.ProfileData], + }); + }, + }); +}; + +export default useAllowFriendMutation; diff --git a/frontend/src/hooks/useCancelRequestMutation.ts b/frontend/src/hooks/useCancelRequestMutation.ts new file mode 100644 index 0000000..7f6cc38 --- /dev/null +++ b/frontend/src/hooks/useCancelRequestMutation.ts @@ -0,0 +1,28 @@ +import { useMutation, useQueryClient } from '@tanstack/react-query'; + +import { cancelRequestFriend } from '@api/FriendModal'; + +import { useToast } from '@hooks/useToast'; + +import { reactQueryKeys } from '@util/constants'; + +const useCancelRequestMutation = () => { + const DB_WAITING_TIME = 100; + + const queryClient = useQueryClient(); + const openToast = useToast(); + + return useMutation({ + mutationFn: (receiverId: number) => cancelRequestFriend(receiverId), + onSuccess() { + openToast('친구 신청을 취소했습니다.'); + setTimeout(() => { + queryClient.invalidateQueries({ + queryKey: [reactQueryKeys.SendList], + }); + }, DB_WAITING_TIME); + }, + }); +}; + +export default useCancelRequestMutation; diff --git a/frontend/src/hooks/useCreateDiaryMutation.ts b/frontend/src/hooks/useCreateDiaryMutation.ts new file mode 100644 index 0000000..a9d1813 --- /dev/null +++ b/frontend/src/hooks/useCreateDiaryMutation.ts @@ -0,0 +1,47 @@ +import { useNavigate } from 'react-router-dom'; +import { useMutation, useQueryClient } from '@tanstack/react-query'; + +import { createDiary } from '@api/Edit'; + +import { useToast } from '@hooks/useToast'; + +import { reactQueryKeys, PAGE_URL } from '@util/constants'; + +interface CreateDiaryParams { + title: string; + content: string; + thumbnail?: string; + emotion: string; + tagNames?: string[]; + status: string; +} + +const useCreateDiaryMutation = (userId: string) => { + const queryClient = useQueryClient(); + const openToast = useToast(); + const navigate = useNavigate(); + + return useMutation({ + mutationFn: (params: CreateDiaryParams) => createDiary(params), + onSuccess: () => { + navigate(PAGE_URL.MY_DIARY); + queryClient.invalidateQueries({ + queryKey: [reactQueryKeys.Grass, userId], + refetchType: 'all', + }); + queryClient.invalidateQueries({ + queryKey: [reactQueryKeys.EmotionStat, userId], + refetchType: 'all', + }); + queryClient.removeQueries({ + queryKey: [reactQueryKeys.DayDiaryList, userId], + }); + queryClient.removeQueries({ + queryKey: [reactQueryKeys.MyDayDiaryList, userId], + }); + openToast('일기가 작성되었습니다!'); + }, + }); +}; + +export default useCreateDiaryMutation; diff --git a/frontend/src/hooks/useDeleteDiaryMutation.ts b/frontend/src/hooks/useDeleteDiaryMutation.ts new file mode 100644 index 0000000..17c2f79 --- /dev/null +++ b/frontend/src/hooks/useDeleteDiaryMutation.ts @@ -0,0 +1,41 @@ +import { useNavigate } from 'react-router-dom'; +import { useMutation, useQueryClient } from '@tanstack/react-query'; + +import { deleteDiary } from '@api/Detail'; + +import { useToast } from '@hooks/useToast'; + +import { reactQueryKeys } from '@util/constants'; + +const useDeleteDiaryMutation = (userId: string, diaryId: number) => { + const queryClient = useQueryClient(); + const openToast = useToast(); + const navigate = useNavigate(); + + return useMutation({ + mutationFn: () => deleteDiary(diaryId), + onSuccess: () => { + queryClient.invalidateQueries({ + queryKey: [reactQueryKeys.Grass, userId], + refetchType: 'all', + }); + queryClient.invalidateQueries({ + queryKey: [reactQueryKeys.EmotionStat, userId], + refetchType: 'all', + }); + queryClient.removeQueries({ + queryKey: [reactQueryKeys.DayDiaryList, userId], + }); + queryClient.removeQueries({ + queryKey: [reactQueryKeys.MyDayDiaryList, userId], + }); + navigate(-1); + openToast('일기가 삭제되었습니다!'); + }, + onError: (error) => { + console.error(error); + }, + }); +}; + +export default useDeleteDiaryMutation; diff --git a/frontend/src/hooks/useDeleteFriendMutation.ts b/frontend/src/hooks/useDeleteFriendMutation.ts new file mode 100644 index 0000000..fb9a042 --- /dev/null +++ b/frontend/src/hooks/useDeleteFriendMutation.ts @@ -0,0 +1,27 @@ +import { useMutation, useQueryClient } from '@tanstack/react-query'; + +import { deleteFriend } from '@api/FriendModal'; + +import { useToast } from '@hooks/useToast'; + +import { reactQueryKeys } from '@util/constants'; + +const useDeleteFriendMutation = () => { + const queryClient = useQueryClient(); + const openToast = useToast(); + + return useMutation({ + mutationFn: (friendId: number) => deleteFriend(friendId), + onSuccess() { + openToast('친구가 삭제되었습니다.'); + queryClient.invalidateQueries({ + queryKey: [reactQueryKeys.FriendList], + }); + queryClient.invalidateQueries({ + queryKey: [reactQueryKeys.ProfileData], + }); + }, + }); +}; + +export default useDeleteFriendMutation; diff --git a/frontend/src/hooks/useDeleteReactionMutation.ts b/frontend/src/hooks/useDeleteReactionMutation.ts new file mode 100644 index 0000000..9b3cc7f --- /dev/null +++ b/frontend/src/hooks/useDeleteReactionMutation.ts @@ -0,0 +1,26 @@ +import { useMutation, useQueryClient } from '@tanstack/react-query'; + +import { deleteReaction } from '@api/Reaction'; + +import { useToast } from '@hooks/useToast'; + +import { reactQueryKeys } from '@util/constants'; + +const useDeleteReactionMutation = (userId: number, diaryId: number, selectedEmoji: string) => { + const queryClient = useQueryClient(); + const openToast = useToast(); + return useMutation({ + mutationFn: () => deleteReaction(diaryId, selectedEmoji), + onSuccess: () => { + queryClient.removeQueries({ + queryKey: [reactQueryKeys.DayDiaryList, userId], + }); + queryClient.removeQueries({ + queryKey: [reactQueryKeys.MyDayDiaryList, userId], + }); + openToast('공감을 취소했습니다!'); + }, + }); +}; + +export default useDeleteReactionMutation; diff --git a/frontend/src/hooks/usePostReactionMutation.ts b/frontend/src/hooks/usePostReactionMutation.ts new file mode 100644 index 0000000..403a772 --- /dev/null +++ b/frontend/src/hooks/usePostReactionMutation.ts @@ -0,0 +1,26 @@ +import { useMutation, useQueryClient } from '@tanstack/react-query'; + +import { postReaction } from '@api/Reaction'; + +import { useToast } from '@hooks/useToast'; + +import { reactQueryKeys } from '@util/constants'; + +const usePostReactionMutation = (userId: number, diaryId: number, selectedEmoji: string) => { + const queryClient = useQueryClient(); + const openToast = useToast(); + return useMutation({ + mutationFn: () => postReaction(diaryId, selectedEmoji), + onSuccess: () => { + queryClient.removeQueries({ + queryKey: [reactQueryKeys.DayDiaryList, userId], + }); + queryClient.removeQueries({ + queryKey: [reactQueryKeys.MyDayDiaryList, userId], + }); + openToast('공감을 남겼습니다!'); + }, + }); +}; + +export default usePostReactionMutation; diff --git a/frontend/src/hooks/useReactionListQuery.ts b/frontend/src/hooks/useReactionListQuery.ts index d5f5011..2e9c986 100644 --- a/frontend/src/hooks/useReactionListQuery.ts +++ b/frontend/src/hooks/useReactionListQuery.ts @@ -6,7 +6,7 @@ import { reactQueryKeys } from '@util/constants'; const useReactionListQuery = (diaryId: number) => { return useQuery({ - queryKey: [reactQueryKeys, diaryId], + queryKey: [reactQueryKeys.ReactionList, diaryId], queryFn: () => getReactionList(diaryId), }); }; diff --git a/frontend/src/hooks/useRejectFriendMutation.ts b/frontend/src/hooks/useRejectFriendMutation.ts new file mode 100644 index 0000000..8cddb2a --- /dev/null +++ b/frontend/src/hooks/useRejectFriendMutation.ts @@ -0,0 +1,28 @@ +import { useMutation, useQueryClient } from '@tanstack/react-query'; + +import { rejectFriend } from '@api/FriendModal'; + +import { useToast } from '@hooks/useToast'; + +import { reactQueryKeys } from '@util/constants'; + +const useRejectFriendMutation = () => { + const DB_WAITING_TIME = 100; + + const queryClient = useQueryClient(); + const openToast = useToast(); + + return useMutation({ + mutationFn: (senderId: number) => rejectFriend(senderId), + onSuccess() { + openToast('친구 요청을 거절하였습니다.'); + setTimeout(() => { + queryClient.invalidateQueries({ + queryKey: [reactQueryKeys.ReceivedList], + }); + }, DB_WAITING_TIME); + }, + }); +}; + +export default useRejectFriendMutation; diff --git a/frontend/src/hooks/useRequestFriendMutation.ts b/frontend/src/hooks/useRequestFriendMutation.ts new file mode 100644 index 0000000..5854af8 --- /dev/null +++ b/frontend/src/hooks/useRequestFriendMutation.ts @@ -0,0 +1,31 @@ +import { useMutation, useQueryClient } from '@tanstack/react-query'; + +import { requestFriend } from '@api/FriendModal'; + +import { useToast } from '@hooks/useToast'; + +import { reactQueryKeys } from '@util/constants'; + +const useRequestFriendMutation = () => { + const DB_WAITING_TIME = 100; + + const queryClient = useQueryClient(); + const openToast = useToast(); + + return useMutation({ + mutationFn: (senderId: number) => requestFriend(senderId), + onSuccess() { + openToast('친구 요청을 보냈습니다.'); + setTimeout(() => { + queryClient.invalidateQueries({ + queryKey: [reactQueryKeys.SendList], + }); + queryClient.invalidateQueries({ + queryKey: [reactQueryKeys.ProfileData], + }); + }, DB_WAITING_TIME); + }, + }); +}; + +export default useRequestFriendMutation; diff --git a/frontend/src/hooks/useUpdateDiaryMutation.ts b/frontend/src/hooks/useUpdateDiaryMutation.ts new file mode 100644 index 0000000..9feb0cd --- /dev/null +++ b/frontend/src/hooks/useUpdateDiaryMutation.ts @@ -0,0 +1,47 @@ +import { useNavigate } from 'react-router-dom'; +import { useMutation, useQueryClient } from '@tanstack/react-query'; + +import { updateDiary } from '@api/Edit'; + +import { useToast } from '@hooks/useToast'; + +import { reactQueryKeys, PAGE_URL } from '@util/constants'; + +interface CreateDiaryParams { + title: string; + content: string; + thumbnail?: string; + emotion: string; + tagNames?: string[]; + status: string; +} + +const useUpdateDiaryMutation = (userId: string, diaryId: number) => { + const queryClient = useQueryClient(); + const openToast = useToast(); + const navigate = useNavigate(); + + return useMutation({ + mutationFn: (params: CreateDiaryParams) => updateDiary(params, diaryId), + onSuccess: () => { + navigate(`${PAGE_URL.DETAIL}/${diaryId}`); + queryClient.invalidateQueries({ + queryKey: [reactQueryKeys.Grass, userId], + refetchType: 'all', + }); + queryClient.invalidateQueries({ + queryKey: [reactQueryKeys.EmotionStat, userId], + refetchType: 'all', + }); + queryClient.removeQueries({ + queryKey: [reactQueryKeys.DayDiaryList, userId], + }); + queryClient.removeQueries({ + queryKey: [reactQueryKeys.MyDayDiaryList, userId], + }); + openToast('일기가 수정되었습니다!'); + }, + }); +}; + +export default useUpdateDiaryMutation; diff --git a/frontend/src/hooks/useUpdateProfileMutation.ts b/frontend/src/hooks/useUpdateProfileMutation.ts new file mode 100644 index 0000000..1c0b1bf --- /dev/null +++ b/frontend/src/hooks/useUpdateProfileMutation.ts @@ -0,0 +1,27 @@ +import { useMutation, useQueryClient } from '@tanstack/react-query'; + +import { updateProfile } from '@api/FriendModal'; + +import { useToast } from '@hooks/useToast'; + +import { reactQueryKeys } from '@util/constants'; + +const useUpdateProfileMutation = (userId: string) => { + const queryClient = useQueryClient(); + const openToast = useToast(); + + return useMutation({ + mutationFn: (formData: FormData) => updateProfile(formData), + onSuccess() { + queryClient.invalidateQueries({ + queryKey: [reactQueryKeys.ProfileData, userId], + }); + openToast('프로필 정보가 수정되었습니다.'); + }, + onError() { + openToast('사진의 크기는 최대 10MB입니다.'); + }, + }); +}; + +export default useUpdateProfileMutation; diff --git a/frontend/src/pages/Detail.tsx b/frontend/src/pages/Detail.tsx index 69e019e..5115be6 100644 --- a/frontend/src/pages/Detail.tsx +++ b/frontend/src/pages/Detail.tsx @@ -1,8 +1,5 @@ import { useEffect } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; -import { useMutation, useQueryClient } from '@tanstack/react-query'; - -import { deleteDiary } from '@api/Detail'; import NavBar from '@components/Common/NavBar'; import Button from '@components/Common/Button'; @@ -13,49 +10,25 @@ import Loading from '@components/Common/Loading'; import useEditStore from '@store/useEditStore'; -import { useToast } from '@hooks/useToast'; import useModal from '@hooks/useModal'; import useDiaryQuery from '@hooks/useDiaryQuery'; +import useDeleteDiaryMutation from '@hooks/useDeleteDiaryMutation'; import { PAGE_URL } from '@util/constants'; const Detail = () => { - const queryClient = useQueryClient(); - const openToast = useToast(); const navigate = useNavigate(); const { setDiaryId, setTitle, setEmoji, setThumbnail, setContent, setKeywordList, setStatus } = useEditStore(); const { openModal, closeModal } = useModal(); const params = useParams(); + const userId = localStorage.getItem('userId') as string; const diaryId = Number(params.diaryId); const { data, isLoading, isError } = useDiaryQuery(diaryId); - const deleteDiaryMutation = useMutation({ - mutationFn: () => deleteDiary(diaryId), - onSuccess: () => { - queryClient.invalidateQueries({ - queryKey: ['grass', localStorage.getItem('userId')], - refetchType: 'all', - }); - queryClient.invalidateQueries({ - queryKey: ['emotionStat', localStorage.getItem('userId')], - refetchType: 'all', - }); - queryClient.removeQueries({ - queryKey: ['dayDiaryList', localStorage.getItem('userId')], - }); - queryClient.removeQueries({ - queryKey: ['myDayDiaryList', localStorage.getItem('userId')], - }); - navigate(-1); - openToast('일기가 삭제되었습니다!'); - }, - onError: (error) => { - console.error(error); - }, - }); + const deleteDiaryMutation = useDeleteDiaryMutation(userId, diaryId); const handleDelete = () => { deleteDiaryMutation.mutate();