Skip to content

Commit

Permalink
フォローボタンの実装 (#346)
Browse files Browse the repository at this point in the history
## Issue

- Github Issue: #340 

## 変更内容
ユーザー情報取得APIを連携

## 確認方法


## Screenshot (任意)

## ChatGPTによるレビュー (任意)
最下部の一文`@coderabbitai`を削除することで有効となります。
指摘内容に対してコメントすることで対話が可能です。

※まだ精度としては甘いです。あくまで見直すキッカケくらいにお考えください。











<!-- This is an auto-generated comment: release notes by OSS CodeRabbit
-->
### Summary by CodeRabbit

- 新機能:
`FollowButton`コンポーネントが大幅に改善され、新しい`useRelationship`フックを使用してユーザーの関係性を取得し、それに基づいてボタンの表示を切り替えるようになりました。
- リファクタリング: `ProfileCard`コンポーネント内のフォローボタンのレンダリングが簡略化され、不要な条件式が削除されました。
- スタイル: フォローボタンのスタイリングが更新され、マウスのホバーやクリック時の挙動が改善されました。
- 新機能: フォローとアンフォローのための新しい関数が追加され、ユーザーのフォロー状態をより効率的に管理できるようになりました。
<!-- end of auto-generated comment: release notes by OSS CodeRabbit -->

Co-authored-by: takecchi <takecchi.kobayashi@gmail.com>
  • Loading branch information
AyumuAkimoto and takecchi authored Mar 18, 2024
1 parent beb0fb3 commit 1966282
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 22 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Meta, StoryObj } from '@storybook/react';

import { FollowButton } from './FollowButton';
import FollowButton from './FollowButton';

const meta = {
component: FollowButton,
Expand All @@ -13,6 +13,5 @@ type Story = StoryObj<typeof meta>;
export const NormalFollowButton: Story = {
args: {
userId: 123,
isFollowing: true,
},
};
Original file line number Diff line number Diff line change
@@ -1,23 +1,61 @@
'use client';

import CapsuleButton from '@/app/_components/button/CapsuleButton';
import { useRelationship } from '@/swr/client/relationship';
import { useFollowUpdate } from '@/swr/client/user';
import { styled } from '@mui/material';
import { useState } from 'react';

type Props = {
userId: number;
isFollowing: boolean;
};
const RemoveButton = styled(CapsuleButton)`
&:hover {
color: ${({ theme }) => theme.palette.error.main};
border-color: ${({ theme }) => theme.palette.error.main};
}
`;

export function FollowButton({ isFollowing }: Props) {
const text = isFollowing ? 'フォロー中' : 'フォロー';
/**
* フォローボタン
* @param userId
* @constructor
*/
export default function FollowButton({ userId }: { userId: number }) {
const { data: relationship } = useRelationship(userId);
const { trigger: updateFollow } = useFollowUpdate(userId);
const [isHover, setHover] = useState(false);

return (
<CapsuleButton
aria-label={text}
color="primary"
// onClick={onClick}
variant={isFollowing ? 'outlined' : 'contained'}
>
{text}
</CapsuleButton>
);
// ロード中または非ログイン時は何も表示しない
if (!relationship) {
return <></>;
}

// 非フォローの場合はフォローボタンを表示
if (!relationship.following) {
const text = 'フォロー';
return (
<CapsuleButton
aria-label={text}
variant={'contained'}
onClick={() => {
void updateFollow(true);
}}
>
{text}
</CapsuleButton>
);
} else {
// フォロー中の場合はフォロー解除ボタンを表示
return (
<RemoveButton
onMouseEnter={() => setHover(true)}
onMouseLeave={() => setHover(false)}
aria-label={'フォロー解除'}
onClick={() => {
void updateFollow(false);
}}
variant={'outlined'}
>
{isHover ? 'フォロー解除' : 'フォロー中'}
</RemoveButton>
);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use client';

import { Box, Typography, styled } from '@mui/material';
import { FollowButton } from '@/app/(menu)/(public)/[username]/_components/elements/FollowButton';
import FollowButton from '@/app/(menu)/(public)/[username]/_components/elements/FollowButton';
import UserCount from '@/app/(menu)/(public)/[username]/_components/elements/UserCount';
import { usePathname } from 'next/navigation';
import HeaderImage from '@/app/(menu)/(public)/[username]/_components/elements/HeaderImage';
Expand Down Expand Up @@ -109,9 +109,7 @@ export default function ProfileCard({
{/* </IconButton>*/}
{/*)}*/}
{/* フォローボタン */}
{authId && !isMe && (
<FollowButton isFollowing={false} userId={id} />
)}
{authId && !isMe && <FollowButton userId={id} />}
{authId && isMe && <EditProfileButton />}
</HFlex>
</FillFlex>
Expand Down
34 changes: 34 additions & 0 deletions src/swr/client/relationship.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Relationship } from '@cuculus/cuculus-api';
import { useAuth } from '@/swr/client/auth';
import useSWR from 'swr';
import { usersApi } from '@/libs/cuculus-client';
import { getAuthorizationHeader } from '@/libs/auth';

// ユーザーとの関係性を取得するためのキー型
export type RelationshipKey = {
key: 'useRelationship';
userId: number;
authId?: number;
};

/**
* ユーザーとの関係性を取得する
* @param userId
*/
export const useRelationship = (userId: number) => {
const { data: authId } = useAuth();
// 非ログイン時はキー値にnullを渡して実行させないようにする
const key = authId
? { key: 'useRelationship' as const, userId, authId }
: null;
return useSWR<Relationship, Error, RelationshipKey | null>(
key,
async () => {
return await usersApi.getRelationShip(
{ id: userId },
{ headers: await getAuthorizationHeader(authId) },
);
},
{},
);
};
29 changes: 29 additions & 0 deletions src/swr/client/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { UserPost, UserWithFollows } from '@cuculus/cuculus-api';
import { getAuthorizationHeader } from '@/libs/auth';
import { useAuth } from '@/swr/client/auth';
import useSWRTimeline from '@/libs/swr/timeline';
import useSWRMutation from 'swr/mutation';
import { RelationshipKey } from '@/swr/client/relationship';

const LIMIT = 20;

Expand Down Expand Up @@ -80,3 +82,30 @@ export const useUserPosts = (userId: number) => {
},
);
};

/**
* ユーザーIDをフォローする。またはフォローリクエストを送る
* @param userId
*/
export const useFollowUpdate = (userId: number) => {
const { data: authId } = useAuth();
// 非ログイン時はキー値にnullを渡して実行させないようにする
const key = authId
? { key: 'useRelationship' as const, userId, authId }
: null;
return useSWRMutation<void, Error, RelationshipKey | null, boolean>(
key,
async (_, { arg: follow }) => {
const headers = await getAuthorizationHeader(authId);
if (follow) {
await usersApi.createFollow({ id: userId }, { headers });
} else {
await usersApi.deleteFollow({ id: userId }, { headers });
}
},
{
revalidate: true,
populateCache: false,
},
);
};

0 comments on commit 1966282

Please sign in to comment.