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

WIPフォロー・フォロワー一覧 #391

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 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
14 changes: 14 additions & 0 deletions src/app/(menu)/(public)/[username]/_components/Following.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
'use client';

import FollowList from '@/app/(menu)/(public)/[username]/_components/layouts/FollowList';
import { useFollowing } from '@/swr/client/follows';
import { UserWithFollows } from '@cuculus/cuculus-api';

/**
* フォロー一覧表示コンポーネント
* @param user
* @constructor
*/
export default function Following({ user }: { user: UserWithFollows }) {
return <FollowList follows={useFollowing(user.id)} />;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
'use client';
import FollowButton from '@/app/(menu)/(public)/[username]/_components/elements/FollowButton';
import UserIcon from '@/app/(menu)/(public)/[username]/_components/elements/UserIcon';
import { UserWithFollows } from '@cuculus/cuculus-api';
import { Box, Typography, styled } from '@mui/material';

const UnselectableCard = styled('div')`
border-bottom: 1px solid ${({ theme }) => theme.palette.grey[100]};
background-color: ${({ theme }) => theme.palette.background.paper};
color: rgba(0, 0, 0, 0.87);
`;

const Flex = styled(Box)`
display: flex;
flex-wrap: nowrap;
`;

const VFlex = styled(Flex)`
flex-direction: column;
`;

const HFlex = styled(Flex)`
flex-direction: row;
`;

const HFlexS = styled(Flex)`
flex-direction: row;
justify-content: space-between;
`;

const FillFlex = styled(Box)`
flex-grow: 1;
`;

const DisplayName = styled(Typography)`
word-wrap: break-word;
font-weight: bold;
font-size: 20px;
`;

const UserName = styled(Typography)`
color: #8899a6;
font-size: 15px;
`;

const Avater = styled(UserIcon)`
aspect-ratio: 1;
height: 64px;
width: 64px;
margin: auto 10px;
margin-top: 0;

${({ theme }) => theme.breakpoints.down('desktop')} {
margin: auto 10px;
margin-top: 0;
height: 64px;
width: 64px;
}
`;

const Bio = styled(Typography)`
white-space: pre-wrap;
margin-bottom: 12px;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
`;

type FFProfileCardProps = {
displayName: string;
userName: string;
profileAvatarImageUrl: string;
bio: string;
authId: number | undefined;
} & UserWithFollows;

export default function FFProfileCard({
displayname,

Check failure on line 80 in src/app/(menu)/(public)/[username]/_components/layouts/FFProfileCard.tsx

View workflow job for this annotation

GitHub Actions / tests

Property 'displayname' does not exist on type 'FFProfileCardProps'.
username,
profileImageUrl,
bio,
authId,
id,
}: FFProfileCardProps) {
const isMe = id === authId;

Check warning on line 87 in src/app/(menu)/(public)/[username]/_components/layouts/FFProfileCard.tsx

View workflow job for this annotation

GitHub Actions / tests

'isMe' is assigned a value but never used
return (
<UnselectableCard>
<HFlex>
<Avater src={profileImageUrl} alt={'プロフィール画像'} />
<VFlex style={{ margin: '12px 0' }}>
<HFlexS>
<VFlex>
<DisplayName>{displayname}ユーザー表示名</DisplayName>
<UserName>@{username}usernoid</UserName>
</VFlex>
{/* {authId && !isMe && <FollowButton userId={id} />} */}
<FollowButton userId={1} />
</HFlexS>
<FillFlex>
<Bio>
{bio}
あああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああ
</Bio>
</FillFlex>
</VFlex>
</HFlex>
</UnselectableCard>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { SWRInfiniteResponse } from 'swr/infinite';
import { FollowList } from '@cuculus/cuculus-api';

Check failure on line 2 in src/app/(menu)/(public)/[username]/_components/layouts/FollowList.tsx

View workflow job for this annotation

GitHub Actions / tests

Import 'FollowList' conflicts with local value, so must be declared with a type-only import when 'isolatedModules' is enabled.
import { CircularProgress } from '@mui/material';

type Props = {
follows: SWRInfiniteResponse<FollowList | undefined, Error>;
};

/**
* フォロー/フォロワーリスト
* @param follows
* @constructor
*/
export default function FollowList({ follows }: Props) {
const { data, isLoading, size, setSize } = follows;

if (isLoading) {
return (
<div
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
}}
>
<CircularProgress />
</div>
);
}

return (
<>
<div>現在のページ: {size}</div>
<button onClick={() => void setSize(size + 1)}>次のページへ</button>
{data?.map((follow, index) => (
<div key={index}>
{follow?.users.map((user) => (
<div key={user.id}>ユーザー名:{user.name}</div>
))}
</div>
))}
</>
);
}
20 changes: 19 additions & 1 deletion src/app/(menu)/(public)/[username]/followers/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,28 @@
import FFProfileCard from '@/app/(menu)/(public)/[username]/_components/layouts/FFProfileCard';
import ComingSoon from '@/app/(menu)/_components/main/ComingSoon';

Check warning on line 2 in src/app/(menu)/(public)/[username]/followers/page.tsx

View workflow job for this annotation

GitHub Actions / tests

'ComingSoon' is defined but never used
import PrimaryColumn from '@/app/(menu)/_components/main/PrimaryColumn';

export default function page({}: { params: { userName: string } }) {
return (
<PrimaryColumn hideHeader={true}>
<ComingSoon />
<FFProfileCard />

Check failure on line 8 in src/app/(menu)/(public)/[username]/followers/page.tsx

View workflow job for this annotation

GitHub Actions / tests

Type '{}' is missing the following properties from type '{ displayName: string; userName: string; profileAvatarImageUrl: string; bio: string; authId: number | undefined; }': displayName, userName, profileAvatarImageUrl, bio, authId
<FFProfileCard />

Check failure on line 9 in src/app/(menu)/(public)/[username]/followers/page.tsx

View workflow job for this annotation

GitHub Actions / tests

Type '{}' is missing the following properties from type '{ displayName: string; userName: string; profileAvatarImageUrl: string; bio: string; authId: number | undefined; }': displayName, userName, profileAvatarImageUrl, bio, authId
<FFProfileCard />

Check failure on line 10 in src/app/(menu)/(public)/[username]/followers/page.tsx

View workflow job for this annotation

GitHub Actions / tests

Type '{}' is missing the following properties from type '{ displayName: string; userName: string; profileAvatarImageUrl: string; bio: string; authId: number | undefined; }': displayName, userName, profileAvatarImageUrl, bio, authId
<FFProfileCard />

Check failure on line 11 in src/app/(menu)/(public)/[username]/followers/page.tsx

View workflow job for this annotation

GitHub Actions / tests

Type '{}' is missing the following properties from type '{ displayName: string; userName: string; profileAvatarImageUrl: string; bio: string; authId: number | undefined; }': displayName, userName, profileAvatarImageUrl, bio, authId
<FFProfileCard />

Check failure on line 12 in src/app/(menu)/(public)/[username]/followers/page.tsx

View workflow job for this annotation

GitHub Actions / tests

Type '{}' is missing the following properties from type '{ displayName: string; userName: string; profileAvatarImageUrl: string; bio: string; authId: number | undefined; }': displayName, userName, profileAvatarImageUrl, bio, authId
<FFProfileCard />

Check failure on line 13 in src/app/(menu)/(public)/[username]/followers/page.tsx

View workflow job for this annotation

GitHub Actions / tests

Type '{}' is missing the following properties from type '{ displayName: string; userName: string; profileAvatarImageUrl: string; bio: string; authId: number | undefined; }': displayName, userName, profileAvatarImageUrl, bio, authId
<FFProfileCard />

Check failure on line 14 in src/app/(menu)/(public)/[username]/followers/page.tsx

View workflow job for this annotation

GitHub Actions / tests

Type '{}' is missing the following properties from type '{ displayName: string; userName: string; profileAvatarImageUrl: string; bio: string; authId: number | undefined; }': displayName, userName, profileAvatarImageUrl, bio, authId
<FFProfileCard />

Check failure on line 15 in src/app/(menu)/(public)/[username]/followers/page.tsx

View workflow job for this annotation

GitHub Actions / tests

Type '{}' is missing the following properties from type '{ displayName: string; userName: string; profileAvatarImageUrl: string; bio: string; authId: number | undefined; }': displayName, userName, profileAvatarImageUrl, bio, authId
<FFProfileCard />
<FFProfileCard />
<FFProfileCard />
<FFProfileCard />
<FFProfileCard />
<FFProfileCard />
<FFProfileCard />
<FFProfileCard />
<FFProfileCard />
{/* <ComingSoon /> */}
</PrimaryColumn>
);
}
36 changes: 33 additions & 3 deletions src/app/(menu)/(public)/[username]/following/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,40 @@
import ComingSoon from '@/app/(menu)/_components/main/ComingSoon';
import PrimaryColumn from '@/app/(menu)/_components/main/PrimaryColumn';
import { cache } from 'react';
import { usersApi } from '@/libs/cuculus-client';
import { notFound } from 'next/navigation';
import Following from '@/app/(menu)/(public)/[username]/_components/Following';

type Params = { params: { username: string } };

const getUser = cache(async (username: string) => {
try {
return await usersApi.getUserByUsername(
{ username },
{
next: {
revalidate: 300,
},
},
);
} catch {
return undefined;
}
});

/**
* フォロー一覧ページ
* @param params
*/
export default async function page({ params }: Params) {
const username = decodeURIComponent(params.username);
const user = await getUser(username);
if (!user) {
notFound();
}

export default function page({}: { params: { userName: string } }) {
return (
<PrimaryColumn hideHeader={true}>
<ComingSoon />
<Following user={user} />
</PrimaryColumn>
);
}
53 changes: 53 additions & 0 deletions src/swr/client/follows.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { useAuth } from '@/swr/client/auth';
import { usersApi } from '@/libs/cuculus-client';
import { getAuthorizationHeader } from '@/libs/auth';
import useSWRInfinite from 'swr/infinite';
import { FollowList } from '@cuculus/cuculus-api';

// FIXME 確認用に一旦10件にしている
const LIMIT = 10;

type SWRKey = {
key: string;
authId?: number;
userId: number;
nextUntil?: Date;
};

/**
* フォロー一覧の取得
* @param userId
*/
export const useFollowing = (userId: number) => {
const { data: authId } = useAuth();
return useSWRInfinite<
FollowList | undefined,
Error,
(index: number, prev: FollowList | undefined) => SWRKey | null
>(
(index, previousPageData) => {
// 取得結果が空の場合は次のページがないと判断して終了
if (previousPageData && !previousPageData.users.length) {
return null;
}
return {
key: 'useFollowing',
authId,
userId,
nextUntil: previousPageData?.nextUntil,
};
},
async (args) => {
try {
return await usersApi.getUserFollowing(
{ id: args.userId, until: args.nextUntil, limit: LIMIT },
{
headers: await getAuthorizationHeader(authId),
},
);
} catch (error) {
throw error;
}
},
);
};
Loading