waveform/components/sidebar/DirectMessageSidebar.tsx

121 lines
4.1 KiB
TypeScript

/**
* @file components/sidebar/DirectMessageSidebar.tsx
* @description Sidebar listing direct messages and friends list when no server is selected.
*/
"use client";
import { useSidebarStore } from "@/lib/stores/useSidebarStore";
import { PanelLeftClose, Users } from "lucide-react";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { clsx } from "clsx";
import { UserAvatar } from "@/components/ui/UserAvatar";
import { FriendUser } from "../friends/FriendsView";
/**
* Represents a direct message conversation in the sidebar.
*
* @interface SidebarConversation
* @property {string} id - The unique identifier of the conversation.
* @property {FriendUser} partner - The other user participating in the conversation.
*/
export interface SidebarConversation {
id: string;
partner: FriendUser;
}
/**
* Properties for the DirectMessageSidebar component.
*
* @interface DirectMessageSidebarProps
* @property {SidebarConversation[]} [conversations=[]] - Array of active direct message conversations.
*/
interface DirectMessageSidebarProps {
conversations?: SidebarConversation[];
}
/**
* Renders the direct message sidebar with navigation options, friends view link, and a list of active DM chats.
*
* @param {DirectMessageSidebarProps} props - The component props.
* @param {SidebarConversation[]} [props.conversations=[]] - Array of active direct message conversations.
* @returns {JSX.Element} The rendered direct message sidebar.
*/
export function DirectMessageSidebar({
conversations = [],
}: DirectMessageSidebarProps) {
const { toggleNav } = useSidebarStore();
const pathname = usePathname();
return (
<div className="flex-1 w-full md:w-60 bg-surface/50 border-r border-background flex flex-col h-full shrink-0">
{/* Header */}
<div className="h-14 border-b border-background flex items-center justify-between px-4 font-bold text-white shadow-sm">
<span>Direct Messages</span>
<button
type="button"
onClick={toggleNav}
title="Collapse the sidebar"
className="p-1.5 rounded-md text-muted hover:text-white hover:bg-surface transition-colors cursor-pointer"
>
<PanelLeftClose className="w-5 h-5" />
</button>
</div>
{/* Navigation & List */}
<div className="flex-1 overflow-y-auto p-3 space-y-4">
<div className="space-y-1">
<Link
href="/"
className={clsx(
"flex items-center gap-3 px-3 py-2 rounded-md text-sm font-medium transition-all",
pathname === "/"
? "text-white bg-accent/20"
: "text-muted hover:text-white hover:bg-surface/50",
)}
>
<Users className="w-4 h-4" />
<span className="font-bold">Friends</span>
</Link>
</div>
<div>
<div className="text-xs font-semibold text-muted px-2 mb-2 uppercase tracking-wider">
All Messages
</div>
{conversations.length === 0 ? (
<div className="text-sm text-muted px-2 py-1 italic">
No active chats
</div>
) : (
<div className="space-y-0.5">
{conversations.map((c) => {
const isActive = pathname === `/dm/${c.id}`;
return (
<Link
key={c.id}
href={`/dm/${c.id}`}
className={clsx(
"flex items-center gap-3 px-2 py-1.5 rounded-md text-sm font-medium transition-colors",
isActive
? "bg-accent/20 text-white"
: "text-muted hover:text-white hover:bg-surface/50",
)}
>
{/* UserAvatar Integration */}
<UserAvatar user={c.partner} size="xs" />
<span className="truncate">{c.partner.username}</span>
</Link>
);
})}
</div>
)}
</div>
</div>
</div>
);
}