Files
learn-languages/src/components/follow/FollowButton.tsx
goddonebianu 683a4104ec feat: 添加用户关注功能
- 新增 Follow 表和 User.bio 字段 (Prisma schema)
- 创建 follow 模块 (action-service-repository)
- 新增 FollowButton/FollowStats/UserList 组件
- 用户页面显示 bio、粉丝/关注数、关注按钮
- 新增 /users/[username]/followers 和 following 页面
- 添加 en-US/zh-CN i18n 翻译

⚠️ 需要运行: prisma migrate dev --name add_follow_and_bio
2026-03-10 14:58:43 +08:00

48 lines
1.4 KiB
TypeScript

"use client";
import { useState, useTransition } from "react";
import { PrimaryButton, LightButton } from "@/design-system/base/button";
import { actionToggleFollow } from "@/modules/follow/follow-action";
import { toast } from "sonner";
interface FollowButtonProps {
targetUserId: string;
initialIsFollowing: boolean;
onFollowChange?: (isFollowing: boolean, followersCount: number) => void;
}
export function FollowButton({
targetUserId,
initialIsFollowing,
onFollowChange,
}: FollowButtonProps) {
const [isFollowing, setIsFollowing] = useState(initialIsFollowing);
const [isPending, startTransition] = useTransition();
const handleToggleFollow = () => {
startTransition(async () => {
const result = await actionToggleFollow({ targetUserId });
if (result.success && result.data) {
setIsFollowing(result.data.isFollowing);
onFollowChange?.(result.data.isFollowing, result.data.followersCount);
} else {
toast.error(result.message || "Failed to update follow status");
}
});
};
if (isFollowing) {
return (
<LightButton onClick={handleToggleFollow} disabled={isPending}>
{isPending ? "..." : "Following"}
</LightButton>
);
}
return (
<PrimaryButton onClick={handleToggleFollow} disabled={isPending}>
{isPending ? "..." : "Follow"}
</PrimaryButton>
);
}