3042ddca38
- /wa-inbox, /wa-sessions e /wa-secretaria rodam sem a sidebar do scoreodonto (isStandaloneView); cada tela tem seu "Voltar" (Secretária ganhou botão na ThinNav). - SessionsView: banner "Você já possui acesso ao WhatsApp" quando há sessão ativa. - avatares: usa a URL do CDN (contactAvatarUrl/instance.avatar) direto; Avatar exibe sem depender de version; self-heal no onError re-busca a foto atual. - deps: framer-motion, immer. Dev override com HMR (docker-compose.dev.yml). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
108 lines
4.1 KiB
TypeScript
108 lines
4.1 KiB
TypeScript
'use client';
|
|
|
|
import React, { useMemo, useState } from 'react';
|
|
import type { NewWhatsChat, PresenceState } from '../types/inboxTypes';
|
|
import ChatList from './ChatList';
|
|
|
|
interface ChatSidebarProps {
|
|
chats: NewWhatsChat[];
|
|
loading: boolean;
|
|
selectedChat: NewWhatsChat | null;
|
|
searchTerm: string;
|
|
selectedLabelFilter: string | null;
|
|
activeFilter: string;
|
|
chatScope: 'inbox' | 'favorites' | 'archived' | 'custom_list';
|
|
activeCustomListName?: string | null;
|
|
presenceByJid: Record<string, PresenceState>;
|
|
isFavoriteChat: (chat: NewWhatsChat) => boolean;
|
|
onSelectChat: (chat: NewWhatsChat) => void;
|
|
onMenuAction: (action: any, chat: NewWhatsChat) => void;
|
|
drafts?: Record<string, string>;
|
|
}
|
|
|
|
export default function ChatSidebar({
|
|
chats,
|
|
loading,
|
|
selectedChat,
|
|
searchTerm,
|
|
selectedLabelFilter,
|
|
activeFilter,
|
|
chatScope,
|
|
activeCustomListName,
|
|
presenceByJid,
|
|
isFavoriteChat,
|
|
onSelectChat,
|
|
onMenuAction,
|
|
drafts = {},
|
|
}: ChatSidebarProps) {
|
|
// UI Pills (Simplified, for now we keep layout consistent)
|
|
const [pillFilter, setPillFilter] = useState<'all' | 'unread' | 'favorites' | 'groups'>('all');
|
|
|
|
const filteredChats = useMemo(() => chats.filter((chat) => {
|
|
const isGroup = chat.remote_jid.endsWith('@g.us');
|
|
|
|
// Filter by pill
|
|
if (pillFilter === 'unread' && chat.unread_count === 0) return false;
|
|
if (pillFilter === 'groups' && !isGroup) return false;
|
|
if (pillFilter === 'favorites' && !isFavoriteChat(chat)) return false;
|
|
|
|
const displayName = chat.displayName || chat.subject || chat.phone || chat.remote_jid;
|
|
const matchesSearch = displayName.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
|
(chat.last_message_text || '').toLowerCase().includes(searchTerm.toLowerCase());
|
|
|
|
const matchesLabel = !selectedLabelFilter ||
|
|
(chat.labels && chat.labels.some((l) => l.label_id === selectedLabelFilter));
|
|
|
|
return matchesSearch && matchesLabel;
|
|
}), [chats, searchTerm, selectedLabelFilter, pillFilter, isFavoriteChat]);
|
|
|
|
const sortedFilteredChats = useMemo(
|
|
() => [...filteredChats].sort((a, b) => {
|
|
const aPinned = Boolean(a.is_pinned);
|
|
const bPinned = Boolean(b.is_pinned);
|
|
if (aPinned !== bPinned) return aPinned ? -1 : 1;
|
|
const tA = a.last_message_time ? new Date(a.last_message_time).getTime() : 0;
|
|
const tB = b.last_message_time ? new Date(b.last_message_time).getTime() : 0;
|
|
return tB - tA;
|
|
}),
|
|
[filteredChats]
|
|
);
|
|
|
|
|
|
return (
|
|
<div className="flex flex-col h-full bg-white border-r border-[#e9edef] overflow-hidden">
|
|
{/* Filter Pills */}
|
|
<div className="px-3 py-2 flex items-center gap-2 overflow-x-auto no-scrollbar flex-shrink-0 border-b border-[#f0f2f5]">
|
|
{(['all', 'unread', 'favorites', 'groups'] as const).map((filter) => (
|
|
<button
|
|
key={filter}
|
|
onClick={() => setPillFilter(filter)}
|
|
className={`px-3 py-1 rounded-full text-sm whitespace-nowrap transition-colors ${
|
|
pillFilter === filter
|
|
? 'bg-[#00a884] text-white'
|
|
: 'bg-[#f0f2f5] text-[#54656f] hover:bg-[#e9edef]'
|
|
}`}
|
|
>
|
|
{filter === 'all' && 'Tudo'}
|
|
{filter === 'unread' && 'Não lidas'}
|
|
{filter === 'favorites' && 'Favoritos'}
|
|
{filter === 'groups' && 'Grupos'}
|
|
</button>
|
|
))}
|
|
</div>
|
|
|
|
{/* Scrollable Chat List */}
|
|
<ChatList
|
|
chats={sortedFilteredChats}
|
|
loading={loading}
|
|
selectedChat={selectedChat}
|
|
onSelectChat={onSelectChat}
|
|
onMenuAction={onMenuAction}
|
|
presenceByJid={presenceByJid}
|
|
isFavoriteChat={isFavoriteChat}
|
|
drafts={drafts}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|