waveform/components/members/MemberList.tsx
Chneemann e2985c53a2
All checks were successful
Deploy Waveform to VPS / deploy (push) Successful in 1m9s
feat(members): integrate UserProfilePopover into MemberSidebar
2026-09-09 09:29:19 +02:00

77 lines
2.2 KiB
TypeScript

/**
* @file components/members/MemberList.tsx
* @description Renders categorized lists of online and offline members with their friendship statuses.
*/
import { useMemo } from "react";
import { MemberItem } from "@/components/members/MemberItem";
import { User } from "@/db/schema";
/** Props for the MemberList component. */
interface MemberListProps {
members: User[];
currentUserId: string;
userFriendships: Array<{
senderId: string;
receiverId: string;
status: string;
}>;
}
/** Renders online and offline community members in distinct sections. */
export function MemberList({
members = [],
currentUserId,
userFriendships = [],
}: MemberListProps) {
const { onlineMembers, offlineMembers } = useMemo(() => {
return {
onlineMembers: members.filter((m) => m.status !== "OFFLINE"),
offlineMembers: members.filter((m) => m.status === "OFFLINE"),
};
}, [members]);
return (
<div className="w-full bg-surface p-3 shrink-0 h-full overflow-y-auto space-y-4">
{/* Online Section */}
<div>
<h2 className="text-xs font-semibold text-muted uppercase tracking-wider px-2 mb-1.5">
Online {onlineMembers.length}
</h2>
<div className="space-y-0.5">
{onlineMembers.map((member) => (
<MemberItem
key={member.id}
member={member}
currentUserId={currentUserId}
userFriendships={userFriendships}
/>
))}
{onlineMembers.length === 0 && (
<p className="text-xs text-muted/60 px-2 italic">
No members online
</p>
)}
</div>
</div>
{/* Offline Section */}
<div>
<h2 className="text-xs font-semibold text-muted uppercase tracking-wider px-2 mb-1.5">
Offline {offlineMembers.length}
</h2>
<div className="space-y-0.5">
{offlineMembers.map((member) => (
<MemberItem
key={member.id}
member={member}
currentUserId={currentUserId}
userFriendships={userFriendships}
isOffline
/>
))}
</div>
</div>
</div>
);
}