122 lines
3.6 KiB
TypeScript
122 lines
3.6 KiB
TypeScript
import { Avatar } from './Avatar';
|
|
import { cn } from '../lib/utils';
|
|
import { Friend, FriendRequest } from '../stores/friendStore';
|
|
|
|
interface FriendCardProps {
|
|
friend: Friend;
|
|
onRemove?: () => void;
|
|
onInvite?: () => void;
|
|
className?: string;
|
|
}
|
|
|
|
export function FriendCard({ friend, onRemove, onInvite, className }: FriendCardProps) {
|
|
return (
|
|
<div
|
|
className={cn(
|
|
'flex items-center gap-3 px-3 py-2.5 rounded-lg hover:bg-bg-tertiary transition-colors group',
|
|
className
|
|
)}
|
|
>
|
|
<Avatar
|
|
seed={friend.avatar_seed}
|
|
name={friend.username}
|
|
size="md"
|
|
showOnline
|
|
isOnline={friend.is_online}
|
|
/>
|
|
<div className="flex-1 min-w-0">
|
|
<p className="text-sm font-medium text-text-primary truncate">{friend.username}</p>
|
|
<p className="text-xs text-text-muted">{friend.is_online ? '在线' : '离线'}</p>
|
|
</div>
|
|
<div className="flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity">
|
|
{onInvite && friend.is_online && (
|
|
<button
|
|
onClick={onInvite}
|
|
className="p-1.5 rounded text-text-muted hover:text-accent-green hover:bg-accent-green/10 transition-colors"
|
|
title="邀请加入房间"
|
|
>
|
|
<svg
|
|
className="w-4 h-4"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="2"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
>
|
|
<path d="M16 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" />
|
|
<circle cx="8.5" cy="7" r="4" />
|
|
<line x1="20" y1="8" x2="20" y2="14" />
|
|
<line x1="23" y1="11" x2="17" y2="11" />
|
|
</svg>
|
|
</button>
|
|
)}
|
|
{onRemove && (
|
|
<button
|
|
onClick={onRemove}
|
|
className="p-1.5 rounded text-text-muted hover:text-accent-red hover:bg-accent-red/10 transition-colors"
|
|
title="删除好友"
|
|
>
|
|
<svg
|
|
className="w-4 h-4"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="2"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
>
|
|
<polyline points="3 6 5 6 21 6" />
|
|
<path d="M19 6l-1 14H6L5 6" />
|
|
<path d="M10 11v6M14 11v6" />
|
|
<path d="M9 6V4h6v2" />
|
|
</svg>
|
|
</button>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
interface FriendRequestCardProps {
|
|
request: FriendRequest;
|
|
onAccept: () => void;
|
|
onReject?: () => void;
|
|
className?: string;
|
|
}
|
|
|
|
export function FriendRequestCard({
|
|
request,
|
|
onAccept,
|
|
onReject,
|
|
className,
|
|
}: FriendRequestCardProps) {
|
|
return (
|
|
<div
|
|
className={cn(
|
|
'flex items-center gap-3 px-3 py-2.5 rounded-lg bg-bg-tertiary',
|
|
className
|
|
)}
|
|
>
|
|
<Avatar seed={request.avatar_seed} name={request.username} size="md" />
|
|
<div className="flex-1 min-w-0">
|
|
<p className="text-sm font-medium text-text-primary truncate">{request.username}</p>
|
|
<p className="text-xs text-text-muted">想加你为好友</p>
|
|
</div>
|
|
<div className="flex items-center gap-2">
|
|
{onReject && (
|
|
<button
|
|
onClick={onReject}
|
|
className="btn-ghost py-1 px-2 text-xs"
|
|
>
|
|
拒绝
|
|
</button>
|
|
)}
|
|
<button onClick={onAccept} className="btn-primary py-1 px-3 text-xs">
|
|
接受
|
|
</button>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|