-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
This reverts commit 248dce5.
- Loading branch information
1 parent
248dce5
commit 12de3f6
Showing
22 changed files
with
498 additions
and
14 deletions.
There are no files selected for viewing
22 changes: 22 additions & 0 deletions
22
client/src/app/(protectedRoute)/user/follow-list/layout.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
"use client"; | ||
import CustomAppbar from "@/components/layout/CustomAppbar"; | ||
import CustomContainer from "@/components/layout/CustomContainer"; | ||
import { useMyInfoQuery } from "@/queries/auth/useMyInfoQuery"; | ||
import { ReactNode } from "react"; | ||
|
||
type FollowListLayoutProps = { | ||
children: ReactNode; | ||
}; | ||
|
||
const FollowListLayout = ({ children }: FollowListLayoutProps) => { | ||
const { data: myInfo } = useMyInfoQuery(); | ||
|
||
return ( | ||
<> | ||
<CustomAppbar title={`${myInfo?.nickname??'닉네임'}의 목록`}/> | ||
<CustomContainer>{children}</CustomContainer> | ||
</> | ||
); | ||
}; | ||
|
||
export default FollowListLayout; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
"use client"; | ||
|
||
import { Box } from "@mui/material"; | ||
import CustomToggleButtonGroup from "@/components/CustomToggleButtonGroup"; | ||
import { appbarHeight } from "@/const/uiSizes"; | ||
import { Suspense, useState } from "react"; | ||
import FollowingList from "@/components/user/followList/FollowingList"; | ||
import FollowingUserCardSkeleton from "@/components/user/followList/FollowingUserCardSkeleton"; | ||
import ComponentRepeater from "@/components/ComponentRepeater"; | ||
import FollowerList from "@/components/user/followList/FollowerList"; | ||
|
||
const FollowListPage = () => { | ||
const selectableList = ["팔로잉", "팔로워"]; | ||
const [currentView, setCurrentView] = useState(selectableList[0]); | ||
|
||
return ( | ||
<> | ||
<CustomToggleButtonGroup | ||
value={selectableList} | ||
onChange={setCurrentView} | ||
sx={{ position: "fixed", top: appbarHeight, left: 0, right: 0 }} | ||
/> | ||
{/* Fixed로 빠진 button 위치만큼의 place holder */} | ||
<Box height={26} /> | ||
<Suspense | ||
fallback={ | ||
<ComponentRepeater count={5}> | ||
<FollowingUserCardSkeleton /> | ||
</ComponentRepeater> | ||
} | ||
> | ||
{currentView === "팔로잉" && <FollowingList /> } | ||
{currentView === "팔로워" && <FollowerList /> } | ||
</Suspense> | ||
</> | ||
); | ||
}; | ||
|
||
export default FollowListPage; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { cloneElement, ReactComponentElement } from "react"; | ||
|
||
type Props = { | ||
children: ReactComponentElement<any>; | ||
count: number; | ||
}; | ||
|
||
const ComponentRepeater = ({ children, count }: Props) => { | ||
return ( | ||
<> | ||
{Array.from(new Array(count)).map((_e, i) => | ||
cloneElement(children, { key: i }) | ||
)} | ||
</> | ||
); | ||
}; | ||
|
||
export default ComponentRepeater; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
"use client"; | ||
import { | ||
ToggleButton, | ||
ToggleButtonGroup, | ||
ToggleButtonGroupProps, | ||
Typography, | ||
} from "@mui/material"; | ||
import { useState } from "react"; | ||
|
||
interface CustomToggleButtonGroupType | ||
extends Omit<ToggleButtonGroupProps, "onChange" | "value" | "children"> { | ||
onChange: (val: string) => void; | ||
value: string[]; | ||
} | ||
|
||
const CustomToggleButtonGroup = ({ | ||
onChange, | ||
value, | ||
sx, | ||
...toggleBtnGroupProps | ||
}: CustomToggleButtonGroupType) => { | ||
const [currentValue, setCurrentValue] = useState(value[0]); | ||
|
||
return ( | ||
<ToggleButtonGroup | ||
value={currentValue} | ||
exclusive | ||
fullWidth | ||
onChange={(_e, val) => { | ||
if (val !== null) { | ||
setCurrentValue(val); | ||
onChange(val); | ||
} | ||
}} | ||
sx={{ backgroundColor: "background.paper",px:2, ...sx }} | ||
{...toggleBtnGroupProps} | ||
> | ||
{value.map((val, i) => { | ||
return ( | ||
<ToggleButton | ||
key={i} | ||
disableRipple | ||
value={val} | ||
fullWidth | ||
sx={ToggleButtonStyle} | ||
> | ||
<Typography fontSize="caption1" fontWeight="bold"> | ||
{val} | ||
</Typography> | ||
</ToggleButton> | ||
); | ||
})} | ||
</ToggleButtonGroup> | ||
); | ||
}; | ||
|
||
const ToggleButtonStyle = { | ||
border: 0, | ||
borderRadius: 0, | ||
"&.Mui-selected": { | ||
backgroundColor: "background.paper", | ||
borderBottom: "1px solid", | ||
":hover": { | ||
backgroundColor: "background.paper", | ||
}, | ||
}, | ||
":hover": { | ||
backgroundColor: "background.paper", | ||
}, | ||
}; | ||
|
||
export default CustomToggleButtonGroup; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import { Button, Stack, Typography } from "@mui/material"; | ||
import React from "react"; | ||
import UserAvatar from "@/components/user/info/UserAvatar"; | ||
import { useRouter } from "next/navigation"; | ||
import { USER_PAGE } from "@/const/clientPath"; | ||
import useUnFollowMutation from "@/queries/user/useUnFollowMutation"; | ||
|
||
type Props = { | ||
imageUrl?: string; | ||
nickName: string; | ||
userId: string; | ||
content: string; | ||
userPk: number; | ||
}; | ||
|
||
const FollowUserCard = ({ | ||
userPk, | ||
imageUrl, | ||
nickName, | ||
userId, | ||
content, | ||
}: Props) => { | ||
const router = useRouter(); | ||
const { mutate: unfollowHandler } = useUnFollowMutation(); | ||
|
||
return ( | ||
<Stack direction="row" gap={1} py={1}> | ||
<UserAvatar | ||
src={imageUrl} | ||
alt={`${nickName}의 프로필`} | ||
fallback={nickName} | ||
onClick={() => router.push(USER_PAGE(userPk))} | ||
sx={{ cursor: "pointer" }} | ||
/> | ||
<Stack gap={1} flexGrow={1}> | ||
<Stack direction="row" justifyContent={"space-between"}> | ||
<Stack | ||
sx={{ cursor: "pointer" }} | ||
onClick={() => router.push(USER_PAGE(userPk))} | ||
> | ||
<Typography fontSize="caption1" color="text.main"> | ||
{nickName} | ||
</Typography> | ||
<Typography fontSize="caption2" color="text.secondary"> | ||
@{userId} | ||
</Typography> | ||
</Stack> | ||
<Button | ||
variant="outlined" | ||
onClick={() => unfollowHandler(String(userPk))} | ||
> | ||
언팔로우 | ||
</Button> | ||
</Stack> | ||
<Typography>{content}</Typography> | ||
</Stack> | ||
</Stack> | ||
); | ||
}; | ||
|
||
export default FollowUserCard; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
"use client"; | ||
|
||
import FollowUserCard from "@/components/user/followList/FollowUserCard"; | ||
import { useEffect } from "react"; | ||
import { useInView } from "react-intersection-observer"; | ||
import FollowingUserCardSkeleton from "@/components/user/followList/FollowingUserCardSkeleton"; | ||
import ComponentRepeater from "@/components/ComponentRepeater"; | ||
import useFollowerUserInfiniteQuery from "@/queries/user/useFollowerUserInfiniteQuery"; | ||
|
||
const FollowerList = () => { | ||
const { data, isFetchingNextPage, hasNextPage, fetchNextPage } = | ||
useFollowerUserInfiniteQuery(); | ||
const { ref, inView } = useInView(); | ||
|
||
useEffect(() => { | ||
if (hasNextPage && inView) fetchNextPage(); | ||
}, [inView, hasNextPage]); | ||
|
||
return ( | ||
<> | ||
{data.pages.map((page) => | ||
page.content.map(({ nickname, id, introduction }) => ( | ||
<FollowUserCard | ||
key={id} | ||
nickName={nickname} | ||
userId={id} | ||
content={introduction} | ||
/> | ||
)) | ||
)} | ||
{isFetchingNextPage ? ( | ||
<ComponentRepeater count={5}> | ||
<FollowingUserCardSkeleton /> | ||
</ComponentRepeater> | ||
) : ( | ||
// 인터섹션옵저버 | ||
hasNextPage && <div style={{ height: 60 }} ref={ref}></div> | ||
)} | ||
</> | ||
); | ||
}; | ||
|
||
export default FollowerList; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
"use client"; | ||
|
||
import FollowUserCard from "@/components/user/followList/FollowUserCard"; | ||
import useFollowingUserInfiniteQuery from "@/queries/user/useFollowingUserInfiniteQuery"; | ||
import { useEffect } from "react"; | ||
import { useInView } from "react-intersection-observer"; | ||
import FollowingUserCardSkeleton from "@/components/user/followList/FollowingUserCardSkeleton"; | ||
import ComponentRepeater from "@/components/ComponentRepeater"; | ||
|
||
const FollowingList = () => { | ||
const { data, isFetchingNextPage, hasNextPage, fetchNextPage } = | ||
useFollowingUserInfiniteQuery(); | ||
const { ref, inView } = useInView(); | ||
|
||
useEffect(() => { | ||
if (hasNextPage && inView) fetchNextPage(); | ||
}, [inView, hasNextPage]); | ||
|
||
return ( | ||
<> | ||
{data.pages.map((page) => | ||
page.content.map(({ nickname, id, introduction, profileImgUrls, userNo }) => ( | ||
<FollowUserCard | ||
key={id} | ||
nickName={nickname} | ||
userId={id} | ||
userPk={userNo} | ||
imageUrl={profileImgUrls[0]?.attachUrl} | ||
content={introduction} | ||
/> | ||
)) | ||
)} | ||
{isFetchingNextPage ? ( | ||
<ComponentRepeater count={5}> | ||
<FollowingUserCardSkeleton /> | ||
</ComponentRepeater> | ||
) : ( | ||
// 인터섹션옵저버 | ||
hasNextPage && <div style={{ height: 60 }} ref={ref}></div> | ||
)} | ||
</> | ||
); | ||
}; | ||
|
||
export default FollowingList; |
22 changes: 22 additions & 0 deletions
22
client/src/components/user/followList/FollowingUserCardSkeleton.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { Stack } from "@mui/material"; | ||
import { Skeleton } from "@mui/material"; | ||
|
||
const FollowingUserCardSkeleton = () => { | ||
return ( | ||
<Stack direction="row" gap={1} py={1}> | ||
<Skeleton width={40} height={40} variant="circular" /> | ||
<Stack gap={1} flexGrow={1}> | ||
<Stack direction="row" justifyContent={"space-between"}> | ||
<Stack> | ||
<Skeleton width={50} /> | ||
<Skeleton width={60} /> | ||
</Stack> | ||
<Skeleton height={40} width={80} variant="rectangular" /> | ||
</Stack> | ||
<Skeleton width={"100%"} /> | ||
</Stack> | ||
</Stack> | ||
); | ||
}; | ||
|
||
export default FollowingUserCardSkeleton; |
Oops, something went wrong.