- 新增 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
69 lines
2.0 KiB
TypeScript
69 lines
2.0 KiB
TypeScript
import Image from "next/image";
|
|
import Link from "next/link";
|
|
|
|
interface UserItem {
|
|
id: string;
|
|
username: string | null;
|
|
displayUsername: string | null;
|
|
image: string | null;
|
|
bio: string | null;
|
|
}
|
|
|
|
interface UserListProps {
|
|
users: UserItem[];
|
|
emptyMessage: string;
|
|
}
|
|
|
|
export function UserList({ users, emptyMessage }: UserListProps) {
|
|
if (users.length === 0) {
|
|
return (
|
|
<div className="text-center py-12 text-gray-500">
|
|
{emptyMessage}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="space-y-4">
|
|
{users.map((user) => (
|
|
<Link
|
|
key={user.id}
|
|
href={`/users/${user.username || user.id}`}
|
|
className="flex items-center gap-4 p-4 bg-white rounded-lg shadow-sm hover:shadow-md transition-shadow"
|
|
>
|
|
{user.image ? (
|
|
<div className="relative w-12 h-12 rounded-full overflow-hidden flex-shrink-0">
|
|
<Image
|
|
src={user.image}
|
|
alt={user.displayUsername || user.username || "User"}
|
|
fill
|
|
className="object-cover"
|
|
unoptimized
|
|
/>
|
|
</div>
|
|
) : (
|
|
<div className="w-12 h-12 rounded-full bg-primary-500 flex items-center justify-center flex-shrink-0">
|
|
<span className="text-lg font-bold text-white">
|
|
{(user.displayUsername || user.username || "U")[0].toUpperCase()}
|
|
</span>
|
|
</div>
|
|
)}
|
|
<div className="flex-1 min-w-0">
|
|
<div className="font-semibold text-gray-900 truncate">
|
|
{user.displayUsername || user.username || "Anonymous"}
|
|
</div>
|
|
{user.username && (
|
|
<div className="text-sm text-gray-500">@{user.username}</div>
|
|
)}
|
|
{user.bio && (
|
|
<div className="text-sm text-gray-600 truncate mt-1">
|
|
{user.bio}
|
|
</div>
|
|
)}
|
|
</div>
|
|
</Link>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|