refactor: extract ChatListPanel component and add conditional auto-scroll behavior

This commit is contained in:
Yusuf İpek
2025-10-05 04:42:47 +03:00
parent aef59fb291
commit 0f01640050
7 changed files with 125 additions and 42 deletions
+48 -18
View File
@@ -105,21 +105,22 @@ export default function DashboardPage() {
<div className="panel__header">
<h2>💬 CHAT MESSAGES</h2>
</div>
<div className="chatList">
{regularMessages.map((message) => (
<ChatListPanel
messages={regularMessages}
renderItem={(message) => (
<ChatItem
key={message.id}
message={message}
isSelected={selection?.id === message.id}
onSelect={() => handleSelect(message)}
/>
))}
{regularMessages.length === 0 && (
)}
emptyState={
<div className="chatList__empty">
<p> Waiting for chat messages...</p>
</div>
)}
</div>
}
/>
</div>
<div className="dashboard__grid-right">
@@ -127,42 +128,44 @@ export default function DashboardPage() {
<div className="panel__header">
<h2>🔥 SUPER CHATS</h2>
</div>
<div className="chatList">
{superChats.map((message) => (
<ChatListPanel
messages={superChats}
renderItem={(message) => (
<ChatItem
key={message.id}
message={message}
isSelected={selection?.id === message.id}
onSelect={() => handleSelect(message)}
/>
))}
{superChats.length === 0 && (
)}
emptyState={
<div className="chatList__empty">
<p>No super chats yet</p>
</div>
)}
</div>
}
/>
</div>
<div className="panel panel--members">
<div className="panel__header">
<h2> MEMBERSHIPS & MILESTONES</h2>
</div>
<div className="chatList">
{newMembers.map((message) => (
<ChatListPanel
messages={newMembers}
renderItem={(message) => (
<MemberItem
key={message.id}
message={message}
isSelected={selection?.id === message.id}
onSelect={() => handleSelect(message)}
/>
))}
{newMembers.length === 0 && (
)}
emptyState={
<div className="chatList__empty">
<p>No new members yet</p>
</div>
)}
</div>
}
/>
</div>
</div>
</section>
@@ -380,6 +383,33 @@ type ChatItemProps = {
onSelect: () => void;
};
type ChatListPanelProps = {
messages: ChatMessage[];
renderItem: (message: ChatMessage) => React.ReactNode;
emptyState: React.ReactNode;
};
function ChatListPanel({ messages, renderItem, emptyState }: ChatListPanelProps) {
const scrollRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const node = scrollRef.current;
if (node) {
// Check if user is near the bottom before scrolling
const isAtBottom = node.scrollHeight - node.scrollTop - node.clientHeight <= 100;
if (isAtBottom) {
node.scrollTop = node.scrollHeight;
}
}
}, [messages]);
return (
<div className="chatList" ref={scrollRef}>
{messages.length > 0 ? messages.map(renderItem) : emptyState}
</div>
);
}
function ChatItem({ message, isSelected, onSelect }: ChatItemProps) {
return (
<button
+5 -3
View File
@@ -86,15 +86,17 @@ export default function OverlayPage() {
</div>
{message.superChat && (
<div className="overlay__superchat" style={{ backgroundColor: message.superChat.color }}>
💰 {message.superChat.amount} {message.superChat.currency}
💰 {message.superChat.currency}{message.superChat.amount}
</div>
)}
{message.membershipGift && (
<div className="overlay__membership">
🎁 {message.membershipLevel || 'New Member'}
🎁 New Member!
</div>
)}
<p className="overlay__text">{message.text}</p>
{(!message.superChat && !message.membershipGift) && message.text && (
<p className="overlay__text">{message.text}</p>
)}
</div>
) : (
<div className="overlay__placeholder">