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

글-삭제기능-추가 #43

Merged
merged 2 commits into from
Nov 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions client/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import "./globals.css";
import CustomQueryClientProvider from "@/components/queryClient/CustomQueryClientProvider";
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
import GlobalLoadingPopup from "./../components/GlobalLoadingPopup";
import GlobalToast from "@/components/GlobalToast";

export const metadata: Metadata = {
title: `${nameOfApp} | ${oneLineMessage}`,
Expand All @@ -35,6 +36,7 @@ export default function RootLayout({ children, Modal }: RootLayoutInterface) {
<ThemeRegistry options={{ key: "mui" }}>
<GlobalStyles styles={OverrideCSS} />
<GlobalLoadingPopup />
<GlobalToast/>
{Modal}
<Box
sx={{
jobkaeHenry marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/ErrorPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const ErrorPage = ({
reset: () => void;
}) => {
useEffect(() => {
errorHandler(JSON.stringify(error));
errorHandler(error);
}, [error]);

return (
jobkaeHenry marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
55 changes: 55 additions & 0 deletions client/src/components/GlobalToast.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
"use client";

import {
SnackbarVariant,
useGlobalSnackbarStore,
} from "@/store/useGlobalSnackbarStore";
import { CheckCircle, Error, Warning } from "@mui/icons-material";
import { Snackbar, SnackbarContent, Stack } from "@mui/material";

const GlobalToast = () => {
const { isOpen, variant, message, closeToast } = useGlobalSnackbarStore();
return (
<Snackbar
open={isOpen}
color={variant}
key={message}
onClose={closeToast}
autoHideDuration={3000}
anchorOrigin={{ vertical: "bottom", horizontal: "center" }}
sx={{ mb: 6 }}
>
<SnackbarContent
message={<SnackbarMessage variant={variant} message={message} />}
/>
</Snackbar>
);
};

const SnackbarMessage = ({
message,
variant,
}: {
message: string;
variant: SnackbarVariant;
}) => {
return (
<Stack direction="row" gap={1} alignItems="center">
{IconSelector(variant)}
{message}
</Stack>
);
};

const IconSelector = (variant: SnackbarVariant) => {
switch (variant) {
case "danger":
return <Error sx={{color:'red'}} />;
case "warning":
return <Warning sx={{color:'orange'}}/>;
default:
return <CheckCircle sx={{color:'green'}}/>;
}
};

export default GlobalToast;
jobkaeHenry marked this conversation as resolved.
Show resolved Hide resolved
11 changes: 6 additions & 5 deletions client/src/components/post/PostCard.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client";

import { PostInterface } from "@/types/post/PostInterface";
import { MoreVertOutlined } from "@mui/icons-material";

import {
Box,
Card,
Expand All @@ -28,6 +28,7 @@ import UserAvatar from "../user/info/UserAvatar";
import Link from "next/link";
import { USER_PAGE } from "@/const/clientPath";
import { useMyInfoQuery } from "@/queries/auth/useMyInfoQuery";
import PostCardOptionDropdown from "./PostCardOptionDropdown";

const PostCard = ({
postAttachUrls,
Expand Down Expand Up @@ -56,7 +57,6 @@ const PostCard = ({
() => currentUser?.userNo === createdBy,
[currentUser]
);

return (
<Card sx={{ display: "flex", gap: 2, p: 2 }}>
<Link href={USER_PAGE(createdBy)}>
Expand All @@ -81,6 +81,7 @@ const PostCard = ({
display: "flex",
flexDirection: "row",
gap: 1,
height: 24,
}}
>
{/* 타이틀 */}
Expand All @@ -98,9 +99,9 @@ const PostCard = ({
</Typography>
</Box>

<ButtonBase aria-label="settings" sx={{ p: 0, height: 24 }}>
{isMyPost && <MoreVertOutlined />}
</ButtonBase>
{isMyPost && (
<PostCardOptionDropdown postId={postNo}/>
)}
</Box>

{alcoholName && (
jobkaeHenry marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
39 changes: 39 additions & 0 deletions client/src/components/post/PostCardOptionDropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React, { useState } from "react";
import { MoreVertOutlined } from "@mui/icons-material";
import { ButtonBase, Menu, MenuItem } from "@mui/material";
import { useDeletePostMutation } from "@/queries/post/useDeletePostMutation";

type PostCardOptionDropdownProps = {
postId:number
};

const PostCardOptionDropdown = ({postId}: PostCardOptionDropdownProps) => {
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const open = Boolean(anchorEl);

const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
setAnchorEl(event.currentTarget);
};
const {mutate:deletePost}=useDeletePostMutation()

const handleClose = () => {
setAnchorEl(null);
};
return (
<>
<ButtonBase aria-label="settings" sx={{ p: 0 }} onClick={handleClick}>
<MoreVertOutlined />
</ButtonBase>
<Menu open={open} anchorEl={anchorEl} onClose={handleClose}>
<MenuItem onClick={()=>{
if(confirm('정말 삭제하시겠습니까?')){
deletePost(postId)
}
}}>삭제</MenuItem>
<MenuItem>수정</MenuItem>
</Menu>
</>
);
};

export default PostCardOptionDropdown;
jobkaeHenry marked this conversation as resolved.
Show resolved Hide resolved
4 changes: 3 additions & 1 deletion client/src/components/post/PostDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
import useGetPostDetailQuery from "@/queries/post/useGetPostDetailQuery";
import PostCard from "./PostCard";
import { PostInterface } from "@/types/post/PostInterface";
import { CircularProgress } from "@mui/material";
interface PostDetailInterface {
postNo: string;
initialData: PostInterface;
}
const PostDetail = async ({ postNo, initialData }: PostDetailInterface) => {
const { data } = useGetPostDetailQuery(postNo, { initialData });
return <PostCard {...data} />;
//FIXME 포스트의 좋아요갯수가 업데이트 되지않음
return data ? <PostCard {...data} /> : <CircularProgress />;
};
export default PostDetail;
jobkaeHenry marked this conversation as resolved.
Show resolved Hide resolved
4 changes: 2 additions & 2 deletions client/src/queries/auth/useLoginMutation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ const useLoginMutation = () => {
router.refresh();
router.push(HOME);
},
onError: (error: AxiosError<{ detailMessage: string }>) =>
errorHandler(error.response?.data.detailMessage ?? "에러가 발생했니다"),
onError: (error) =>
errorHandler(error),
onSettled: () => {
setLoading(false);
},
jobkaeHenry marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
4 changes: 4 additions & 0 deletions client/src/queries/auth/useSignupMutation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { SignupRequirement } from "@/types/auth/signupRequirement";
import { useMutation } from "@tanstack/react-query";
import useLoginMutation from "./useLoginMutation";
import { useGlobalLoadingStore } from "@/store/useGlobalLoadingStore";
import errorHandler from "@/utils/errorHandler";

const useSignupMutation = () => {
const { mutate: loginHandler } = useLoginMutation();
Expand All @@ -25,6 +26,9 @@ const useSignupMutation = () => {
onSettled: () => {
setLoading(false);
},
onError: (err) => {
errorHandler(err);
},
});
};

jobkaeHenry marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
2 changes: 2 additions & 0 deletions client/src/queries/newPost/useNewPostMutation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ import axios from "@/libs/axios";
import { POST_LIST } from "@/const/serverPath";
import { NewPostRequestInterface } from "@/types/newPost/NewPostInterface";
import getTokenFromLocalStorage from "@/utils/getTokenFromLocalStorage";
import errorHandler from "@/utils/errorHandler";

const useNewPostMutation = () => {
return useMutation({
mutationFn: async (formData: NewPostRequestInterface) => {
const data = await usePostNewPostFn(formData);
return data;
},
onError: (err) => errorHandler(err),
});
};

jobkaeHenry marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
4 changes: 4 additions & 0 deletions client/src/queries/post/useDeletePostMutation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { REMOVE_POST } from "@/const/serverPath";
import { axiosPrivate } from "@/libs/axios";
import { useMutation } from "@tanstack/react-query";
import { useInvalidatePostList } from "./useGetPostListInfiniteQuery";
import errorHandler from "@/utils/errorHandler";

export const useDeletePostMutation = () => {
const invalidatePreviousData = useInvalidatePostList();
Expand All @@ -10,6 +11,9 @@ export const useDeletePostMutation = () => {
onSuccess: () => {
invalidatePreviousData();
},
onError:(err)=>{
errorHandler(err)
}
});
};

jobkaeHenry marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
4 changes: 4 additions & 0 deletions client/src/queries/post/useLikePostMutation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useMutation, useQueryClient } from "@tanstack/react-query";
import { getPostListInfiniteQueryKey } from "./useGetPostListInfiniteQuery";
import getTokenFromLocalStorage from "@/utils/getTokenFromLocalStorage";
import { POST_LIKE_URL } from "@/const/serverPath";
import errorHandler from "@/utils/errorHandler";
/**
* 좋아요를 수행하고, 게시글을 invalidation 하는 쿼리
* @returns
Expand All @@ -17,6 +18,9 @@ const useLikePostMutation = () => {
queryClient.invalidateQueries({
queryKey: getPostListInfiniteQueryKey.all,
}),
onError:(err)=>{
errorHandler(err)
}
});
};

jobkaeHenry marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
4 changes: 4 additions & 0 deletions client/src/queries/post/useUnLikePostMutation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useMutation, useQueryClient } from "@tanstack/react-query";
import { getPostListInfiniteQueryKey } from "./useGetPostListInfiniteQuery";
import getTokenFromLocalStorage from "@/utils/getTokenFromLocalStorage";
import { POST_UN_LIKE_URL } from "@/const/serverPath";
import errorHandler from "@/utils/errorHandler";
/**
* 좋아요를 취소하고, 게시글을 invalidation 하는 쿼리
* @returns
Expand All @@ -17,6 +18,9 @@ const useLikePostMutation = () => {
queryClient.invalidateQueries({
queryKey: getPostListInfiniteQueryKey.all,
}),
onError:(err)=>{
errorHandler(err)
}
});
};

jobkaeHenry marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
4 changes: 3 additions & 1 deletion client/src/queries/user/useFollowMutation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { UserInfoQueryKey } from "./useUserInfoQuery";
import { UserInfoInterface } from "@/types/user/userInfoInterface";
import { MyInfoQueryKeys } from "../auth/useMyInfoQuery";
import { MyInfoInterface } from "@/types/auth/myInfo";
import errorHandler from "@/utils/errorHandler";

const useFollowMutation = () => {
const queryClient = useQueryClient();
Expand Down Expand Up @@ -39,7 +40,8 @@ const useFollowMutation = () => {
/**
* Mutation 실패시 원래 QuerySnapShot정보로 롤백
*/
onError: (_err, queryFnParams, context) => {
onError: (err, queryFnParams, context) => {
errorHandler(err);
if (!context) {
return;
}
Expand Down
4 changes: 3 additions & 1 deletion client/src/queries/user/useUnFollowMutation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { UserInfoQueryKey } from "./useUserInfoQuery";
import { UserInfoInterface } from "@/types/user/userInfoInterface";
import { MyInfoQueryKeys } from "../auth/useMyInfoQuery";
import { MyInfoInterface } from "@/types/auth/myInfo";
import errorHandler from "@/utils/errorHandler";

const useUnFollowMutation = () => {
const queryClient = useQueryClient();
Expand Down Expand Up @@ -42,7 +43,8 @@ const useUnFollowMutation = () => {
/**
* Mutation 실패시 원래 QuerySnapShot정보로 롤백
*/
onError: (_err, queryFnParams, context) => {
onError: (err, queryFnParams, context) => {
errorHandler(err)
if (!context) {
return;
}
Expand Down
21 changes: 21 additions & 0 deletions client/src/store/useGlobalSnackbarStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { create } from "zustand";

interface GlobalSnackbarStore {
isOpen: boolean;
message: string;
variant: SnackbarVariant;
fireToast: (message: string, variant?: SnackbarVariant) => void;
closeToast:()=>void
}
export type SnackbarVariant = "neutral" | "success" | "danger" | "warning";

export const useGlobalSnackbarStore = create<GlobalSnackbarStore>((set) => ({
isOpen: false,
message: "",
variant: "neutral",
fireToast: (message, variant = "neutral") =>
set({ isOpen: true, message, variant }),
closeToast: () => set((prev) => ({ ...prev, message: "", isOpen: false })),
}));

export const useFireToast =()=> useGlobalSnackbarStore((state)=>state.fireToast)
13 changes: 11 additions & 2 deletions client/src/utils/errorHandler.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
export default function errorHandler(error: string) {
console.log(error);
"use client";
// import { useGlobalSnackbarStore } from "@/store/useGlobalSnackbarStore";
import { isAxiosError } from "axios";

export default function ErrorHandler(error: Error) {
// const { fireToast } = useGlobalSnackbarStore();
if (isAxiosError(error) && error.response) {
// FIXME : Zustand 사용 연구
// error.response.status === 401 && fireToast("로그인 후 이용 가능합니다");
error.response.status === 401 && console.log("로그인 후 이용 가능합니다");
}
}
Loading