From 5f69086290bb890d3340227e24d497396ec6199b Mon Sep 17 00:00:00 2001 From: Jungu Lee <100949102+jobkaeHenry@users.noreply.github.com> Date: Tue, 5 Dec 2023 17:07:42 +0900 Subject: [PATCH] =?UTF-8?q?=EB=8C=93=EA=B8=80-=EC=9E=85=EB=A0=A5=EC=A4=91-?= =?UTF-8?q?Navbar=EB=A5=BC-=EC=88=A8=EA=B8=B0=EB=8A=94=EB=A1=9C=EC=A7=81-?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20(#73)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Minor : Adornment 컴포넌트 커서 포인터로 변경 * Refactor : 전역 컨텍스트 삭제, Event capture 로 대체 * FIX : 브라우저 기본동작 제거 * Refactor : 반복되는 Interface 분리 * Refactor : 반복되는 Interface 분리 * Minor : Hashtag Key 변경 * New : PostList-Api-V2적용 --- .../app/(logoutOnly)/auth/signup/layout.tsx | 2 +- .../src/app/(logoutOnly)/auth/signup/page.tsx | 26 ++++---- .../components/Navigation/NavigationBar.tsx | 9 +-- client/src/components/post/PostCard.tsx | 2 +- client/src/components/post/PostCardList.tsx | 10 ++-- .../src/components/post/PostHashtagList.tsx | 4 +- .../post/detail/PostCommentInput.tsx | 13 ++-- client/src/const/theme.ts | 7 +++ .../post/useGetPostListInfiniteQuery.tsx | 60 +++++++++++-------- client/src/store/post/PostCardContext.ts | 4 +- client/src/store/useGlobalNavbarVisibility.ts | 15 ----- client/src/types/Pagenated.ts | 35 +++++++++++ client/src/types/attach/attachInterface.ts | 5 ++ client/src/types/post/PostInterface.ts | 12 ++-- 14 files changed, 120 insertions(+), 84 deletions(-) delete mode 100644 client/src/store/useGlobalNavbarVisibility.ts create mode 100644 client/src/types/Pagenated.ts create mode 100644 client/src/types/attach/attachInterface.ts diff --git a/client/src/app/(logoutOnly)/auth/signup/layout.tsx b/client/src/app/(logoutOnly)/auth/signup/layout.tsx index 5dfd381..f3620c9 100644 --- a/client/src/app/(logoutOnly)/auth/signup/layout.tsx +++ b/client/src/app/(logoutOnly)/auth/signup/layout.tsx @@ -20,7 +20,7 @@ const layout = ({ children }: layoutProps) => { return ( - (""); const { mutateAsync: signupHandler } = useSignupMutation(); + const submitHandler = useCallback(async (data: SignupRequirement) => { try { await signupHandler(data); @@ -99,7 +100,7 @@ export default function SignUpPage() { > - {MultistepForm} - { - !isLastStep ? next() : submitHandler(formData); - }} - size="large" - disabled={disableBtn} - > - {!isLastStep ? "다음" : "투파이아 시작하기"} - +
{ + e.preventDefault() + !isLastStep ? next() : submitHandler(formData); + }}> + {MultistepForm} + + {!isLastStep ? "다음" : "투파이아 시작하기"} + +
); } diff --git a/client/src/components/Navigation/NavigationBar.tsx b/client/src/components/Navigation/NavigationBar.tsx index 122b669..d2cb3c2 100644 --- a/client/src/components/Navigation/NavigationBar.tsx +++ b/client/src/components/Navigation/NavigationBar.tsx @@ -1,11 +1,10 @@ "use client"; -import { BottomNavigation, BottomNavigationAction, Paper } from "@mui/material"; +import { BottomNavigation, BottomNavigationAction } from "@mui/material"; import HomeIcon from "~/assets/icons/HomeIcon.svg"; import SearchIcon from "~/assets/icons/SearchIcon.svg"; import PostIcon from "~/assets/icons/PostIcon.svg"; import BeverageIcon from "~/assets/icons/BeverageIcon.svg"; -import { useGlobalNavbarVisibility } from "@/store/useGlobalNavbarVisibility"; import HOME, { MY_PROFILE, @@ -24,8 +23,6 @@ const NavigationBar = () => { const path = usePathname(); const { data: userInfo } = useMyInfoQuery(); - const isVisible = useGlobalNavbarVisibility(({ isVisible }) => isVisible); - const NavbarData = useMemo( () => [ { @@ -55,7 +52,7 @@ const NavigationBar = () => { ], [userInfo] ); - return isVisible ? ( + return ( {NavbarData.map(({ label, href, iconComponent, ...others }) => { return ( @@ -71,8 +68,6 @@ const NavigationBar = () => { ); })} - ) : ( - <> ); }; diff --git a/client/src/components/post/PostCard.tsx b/client/src/components/post/PostCard.tsx index 95a68b2..a7f4772 100644 --- a/client/src/components/post/PostCard.tsx +++ b/client/src/components/post/PostCard.tsx @@ -84,7 +84,7 @@ const PostCard = ({ diff --git a/client/src/components/post/PostCardList.tsx b/client/src/components/post/PostCardList.tsx index d5f4541..b507601 100644 --- a/client/src/components/post/PostCardList.tsx +++ b/client/src/components/post/PostCardList.tsx @@ -27,7 +27,7 @@ function PostCardList(props: UseGetPostListQueryInterface) { headers: { Authorization: getTokenFromLocalStorage() }, }); - const { searchKeyword, searchUserNos } = props; + const { searchKeyword, searchUserNos, sort } = props; const { ref, inView } = useInView(); useEffect(() => { @@ -35,18 +35,18 @@ function PostCardList(props: UseGetPostListQueryInterface) { }, [inView, hasNextPage]); const hasResult = useMemo( - () => data && data.pages[0].list.length > 0, + () => data && data.pages[0].content.length > 0, [data] ); return ( - +
{hasResult && isSuccess && // 검색결과가 있을시 data?.pages.map((page) => - page.list.map((post) => ) + page.content.map((post) => ) )} {isSuccess && !hasResult && ( // 검색결과 없을 시 @@ -56,7 +56,7 @@ function PostCardList(props: UseGetPostListQueryInterface) { )} {/* 로딩창 */} {isFetchingNextPage || isLoading ? ( - + ) : ( // 인터섹션옵저버
diff --git a/client/src/components/post/PostHashtagList.tsx b/client/src/components/post/PostHashtagList.tsx index 09fee0c..f9ed4cb 100644 --- a/client/src/components/post/PostHashtagList.tsx +++ b/client/src/components/post/PostHashtagList.tsx @@ -20,8 +20,8 @@ const PostHashTagList = ({ tags, ...others }: TagListInterface) => { }} {...others} > - {tags.map((tag) => ( - + {tags.map((tag,i) => ( + { - const setIsShowingNavbar = useGlobalNavbarVisibility( - ({ setIsVisible }) => setIsVisible - ); const { data: currentData } = useContext(PostDetailPageContext); const [isEditing, setIsEditing] = useState(false); const [inputValue, setInputValue] = useState(""); @@ -33,22 +29,21 @@ const PostCommentInput = () => { border: "1px solid", borderColor: "gray.secondary", position: "fixed", - bottom: isEditing ? 0 : "44px", + bottom: isEditing ? 0 : 56, borderRadius: 1.5, left: 0, right: 0, p: 2, - pb: isEditing ? 2 : 3.5, + zIndex: 2, }} + elevation={0} > { - setIsShowingNavbar(false); setIsEditing(true); }} onBlur={() => { - setIsShowingNavbar(true); setIsEditing(false); }} size="small" @@ -64,7 +59,7 @@ const PostCommentInput = () => { position="end" onClick={(e) => { e.stopPropagation(); - submitHandler(inputValue) + submitHandler(inputValue); }} sx={{ color: inputValue.length > 0 ? "primary.main" : "text.disabled", diff --git a/client/src/const/theme.ts b/client/src/const/theme.ts index 476a5a5..4e55fa7 100644 --- a/client/src/const/theme.ts +++ b/client/src/const/theme.ts @@ -118,6 +118,13 @@ const theme = createTheme({ elevation: 0, }, }, + MuiInputAdornment:{ + styleOverrides:{ + root:{ + cursor:'pointer' + } + } + } }, }); diff --git a/client/src/queries/post/useGetPostListInfiniteQuery.tsx b/client/src/queries/post/useGetPostListInfiniteQuery.tsx index b2f7476..b1e2569 100644 --- a/client/src/queries/post/useGetPostListInfiniteQuery.tsx +++ b/client/src/queries/post/useGetPostListInfiniteQuery.tsx @@ -2,8 +2,9 @@ import { useInfiniteQuery, useQueryClient } from "@tanstack/react-query"; import { PostInterface } from "@/types/post/PostInterface"; import { AxiosRequestConfig } from "axios"; import getTokenFromLocalStorage from "@/utils/getTokenFromLocalStorage"; -import { POST_LIST } from "@/const/serverPath"; +import { POST_LIST_V2 } from "@/const/serverPath"; import useAxiosPrivate from "@/hooks/useAxiosPrivate"; +import Pagenated from "@/types/Pagenated"; export interface UseGetPostListQueryInterface extends GetPostListOptions { initialData?: AugmentedGetPostListResponse; @@ -15,12 +16,14 @@ export const useGetPostListInfiniteQuery = ({ size, searchKeyword, searchUserNos, + sort, headers, }: UseGetPostListQueryInterface) => { return useInfiniteQuery({ queryKey: getPostListInfiniteQueryKey.byKeyword({ - keyword: searchKeyword, - userNo: searchUserNos, + searchKeyword, + searchUserNos, + sort }), queryFn: async ({ pageParam = 0 }) => @@ -29,6 +32,7 @@ export const useGetPostListInfiniteQuery = ({ size, searchKeyword, searchUserNos, + sort, headers: headers?.Authorization ? headers : { Authorization: getTokenFromLocalStorage() }, @@ -54,20 +58,14 @@ export const useGetPostListInfiniteQuery = ({ export interface GetPostListOptions { page?: number; size?: number; + sort?: string; searchKeyword?: string; searchUserNos?: string; } -/** - * 실제 서버에서 응답해주는 값 - */ -export interface GetPostListResponse { - list: PostInterface[]; - totalCount: number; -} /** * 서버응답값 + 무한스크롤을 위해 증강된 값 */ -export interface AugmentedGetPostListResponse extends GetPostListResponse { +export interface AugmentedGetPostListResponse extends Pagenated { currentPage: number; hasNextPage: boolean; } @@ -77,32 +75,46 @@ export const getPostListQueryFn = async ({ size = 10, searchKeyword, searchUserNos, + sort, headers, }: GetPostListOptions & { headers?: AxiosRequestConfig["headers"]; }): Promise => { - const axiosPrivate = useAxiosPrivate() - const { data } = await axiosPrivate.get(POST_LIST, { - baseURL: process.env.NEXT_PUBLIC_BASE_URL, - params: { page, size, searchKeyword, searchUserNos }, - headers, - }); + const axiosPrivate = useAxiosPrivate(); + const { data } = await axiosPrivate.get>( + POST_LIST_V2, + { + baseURL: process.env.NEXT_PUBLIC_BASE_URL, + params: { + page, + size, + searchKeyword, + searchUserNos, + sort: sort ?? "lastModifiedDate,desc", + }, + headers, + } + ); return { ...data, currentPage: page, - hasNextPage: data.totalCount / ((page + 1) * size) > 1, + hasNextPage: data.totalElements / ((page + 1) * size) > 1, }; }; -export interface PostListInfiniteQueryKey { - keyword?: string; - userNo?: string; -} +// export interface PostListInfiniteQueryKey { +// keyword?: string; +// userNo?: string; +// } export const getPostListInfiniteQueryKey = { all: ["posts"] as const, - byKeyword: ({ keyword, userNo }: PostListInfiniteQueryKey) => - ["posts", { keyword, userNo }] as const, + byKeyword: ({ + searchKeyword, + searchUserNos, + sort, + }: Omit) => + ["posts", { searchKeyword, searchUserNos, sort }] as const, }; /** diff --git a/client/src/store/post/PostCardContext.ts b/client/src/store/post/PostCardContext.ts index bc5c1ea..2cfcf01 100644 --- a/client/src/store/post/PostCardContext.ts +++ b/client/src/store/post/PostCardContext.ts @@ -3,13 +3,15 @@ import { createContext } from "react"; export interface PostcardContextInterface { searchKeyword?: string; searchUserNos?: string; + sort?: string; } /** - * 현재 보고있는 페이지의 컨텍스트 + * 현재 보고있는 페이지의 컨텍스트 * (검색,유저페이지,메인페이지의 글 리스트가 같은 쿼리를 바라보고있으므로, * 적절한 Invalidation을 위한 쿼리키를 추출하기 위해 사용됨) */ export const postcardContext = createContext({ searchKeyword: undefined, searchUserNos: undefined, + sort: undefined, }); diff --git a/client/src/store/useGlobalNavbarVisibility.ts b/client/src/store/useGlobalNavbarVisibility.ts deleted file mode 100644 index 070ea60..0000000 --- a/client/src/store/useGlobalNavbarVisibility.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { create } from "zustand"; - -interface GlobalNavbarVisibility { - isVisible: boolean; - setIsVisible: (val: boolean) => void; -} -/** - * 네비게이션바 (바텀네비게이션)을 표시할지 여부 - */ -export const useGlobalNavbarVisibility = create( - (set) => ({ - isVisible: true, - setIsVisible: (val) => set(() => ({ isVisible: val })), - }) -); diff --git a/client/src/types/Pagenated.ts b/client/src/types/Pagenated.ts new file mode 100644 index 0000000..513796b --- /dev/null +++ b/client/src/types/Pagenated.ts @@ -0,0 +1,35 @@ +/** + * T를 입력받아 T를 리턴하는 페이지네이티드 서버 응답 인터페이스로 변환 + */ +export default interface PageNated { + totalPages: number; + totalElements: number; + size: number; + content: T[]; + number: number; + sort: SortInterface; + numberOfElements: number; + first: boolean; + last: boolean; + empty: boolean; +} + +interface SortInterface { + empty: boolean; + sorted: boolean; + unsorted: boolean; + pageable: PageableInterface; +} + +interface PageableInterface { + offset: number; + sort: { + empty: boolean; + sorted: boolean; + unsorted: boolean; + }; + pageNumber: number; + pageSize: number; + paged: boolean; + unpaged: boolean; +} diff --git a/client/src/types/attach/attachInterface.ts b/client/src/types/attach/attachInterface.ts new file mode 100644 index 0000000..e43e343 --- /dev/null +++ b/client/src/types/attach/attachInterface.ts @@ -0,0 +1,5 @@ +export default interface AttachInterface { + attachNo: string; + attachUrl: string; + attachType: string; +} diff --git a/client/src/types/post/PostInterface.ts b/client/src/types/post/PostInterface.ts index 5da6169..ae1e9c3 100644 --- a/client/src/types/post/PostInterface.ts +++ b/client/src/types/post/PostInterface.ts @@ -1,3 +1,5 @@ +import AttachInterface from "../attach/attachInterface"; + /** * 서버로부터 응답받은 포스트 간략정보 */ @@ -49,11 +51,11 @@ export interface PostInterface { /** * 유저가 설정한 프로필 이미지 */ - profileImgUrls: string[]; + profileImgUrls: AttachInterface[]; /** * 이미지 Href 배열 */ - postAttachUrls: postAttachUrlsType[]; + postAttachUrls: AttachInterface[]; /** * 사용자가 추가한 해시태그 */ @@ -88,9 +90,3 @@ type QuoteInfoType = { quoteNo: number; quoteContent: string; }; - -type postAttachUrlsType = { - attachNo:string; - attachUrl:string; - attachType:string -}