File size: 6,555 Bytes
2c6bb7b
 
 
 
 
 
 
 
590318c
 
 
 
2c6bb7b
590318c
2c6bb7b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
import { useState } from 'react'
import { useChatStore } from '@/store/chatStore'
import { useAuthStore } from '@/store/authStore'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import { Badge } from '@/components/ui/badge'
import { ScrollArea } from '@/components/ui/scroll-area'
import {
  Search,
  Plus,
  Settings,
  MessageSquare,
  Users
} from 'lucide-react'
import { formatTime, getInitials } from '@/lib/utils'

export default function ChatSidebar() {
  const { user } = useAuthStore()
  const { chats, currentChat, selectChat, loading } = useChatStore()
  const [searchQuery, setSearchQuery] = useState('')

  const filteredChats = chats.filter(chat => {
    if (!searchQuery) return true
    
    const searchLower = searchQuery.toLowerCase()
    
    // Search by chat name
    if (chat.name?.toLowerCase().includes(searchLower)) return true
    
    // Search by participant names (for direct chats)
    if (chat.type === 'direct') {
      const otherParticipant = chat.participants.find(p => p.userId !== user?.id)
      if (otherParticipant?.user.displayName?.toLowerCase().includes(searchLower)) return true
    }
    
    return false
  })

  const getChatDisplayName = (chat: any) => {
    if (chat.type === 'group') {
      return chat.name || 'Unnamed Group'
    } else {
      const otherParticipant = chat.participants.find((p: any) => p.userId !== user?.id)
      return otherParticipant?.user.displayName || 'Unknown User'
    }
  }

  const getChatAvatar = (chat: any) => {
    if (chat.type === 'group') {
      return chat.avatar
    } else {
      const otherParticipant = chat.participants.find((p: any) => p.userId !== user?.id)
      return otherParticipant?.user.avatar
    }
  }

  return (
    <div className="flex flex-col h-full bg-background">
      {/* Header */}
      <div className="p-4 border-b border-border">
        <div className="flex items-center justify-between mb-4">
          <h1 className="text-xl font-semibold">Chats</h1>
          <div className="flex items-center space-x-2">
            <Button variant="ghost" size="icon">
              <Plus className="w-4 h-4" />
            </Button>
            <Button variant="ghost" size="icon">
              <Settings className="w-4 h-4" />
            </Button>
          </div>
        </div>
        
        {/* Search */}
        <div className="relative">
          <Search className="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-muted-foreground" />
          <Input
            placeholder="Search chats..."
            value={searchQuery}
            onChange={(e) => setSearchQuery(e.target.value)}
            className="pl-10"
          />
        </div>
      </div>

      {/* Chat List */}
      <ScrollArea className="flex-1">
        <div className="p-2">
          {loading ? (
            <div className="flex items-center justify-center py-8">
              <div className="text-muted-foreground">Loading chats...</div>
            </div>
          ) : filteredChats.length === 0 ? (
            <div className="flex flex-col items-center justify-center py-8 text-center">
              <MessageSquare className="w-12 h-12 text-muted-foreground mb-4" />
              <h3 className="font-medium mb-2">No chats found</h3>
              <p className="text-sm text-muted-foreground mb-4">
                {searchQuery ? 'Try a different search term' : 'Start a new conversation'}
              </p>
              <Button size="sm">
                <Plus className="w-4 h-4 mr-2" />
                New Chat
              </Button>
            </div>
          ) : (
            filteredChats.map((chat) => (
              <div
                key={chat.id}
                onClick={() => selectChat(chat.id)}
                className={`
                  flex items-center p-3 rounded-lg cursor-pointer transition-colors
                  hover:bg-accent hover:text-accent-foreground
                  ${currentChat?.id === chat.id ? 'bg-accent text-accent-foreground' : ''}
                `}
              >
                <div className="relative">
                  <Avatar className="w-12 h-12">
                    <AvatarImage src={getChatAvatar(chat)} />
                    <AvatarFallback>
                      {chat.type === 'group' ? (
                        <Users className="w-6 h-6" />
                      ) : (
                        getInitials(getChatDisplayName(chat))
                      )}
                    </AvatarFallback>
                  </Avatar>
                  {/* Online indicator for direct chats */}
                  {chat.type === 'direct' && (
                    <div className="absolute bottom-0 right-0 w-3 h-3 bg-green-500 border-2 border-background rounded-full" />
                  )}
                </div>
                
                <div className="flex-1 ml-3 min-w-0">
                  <div className="flex items-center justify-between">
                    <h3 className="font-medium truncate">
                      {getChatDisplayName(chat)}
                    </h3>
                    <div className="flex items-center space-x-2">
                      {chat.lastMessage && (
                        <span className="text-xs text-muted-foreground">
                          {formatTime(chat.lastMessage.createdAt)}
                        </span>
                      )}
                      {chat.unreadCount > 0 && (
                        <Badge variant="default" className="text-xs">
                          {chat.unreadCount > 99 ? '99+' : chat.unreadCount}
                        </Badge>
                      )}
                    </div>
                  </div>
                  
                  {chat.lastMessage && (
                    <p className="text-sm text-muted-foreground truncate mt-1">
                      {chat.lastMessage.type === 'text' 
                        ? chat.lastMessage.content 
                        : `📎 ${chat.lastMessage.type}`
                      }
                    </p>
                  )}
                  
                  {chat.type === 'group' && (
                    <p className="text-xs text-muted-foreground mt-1">
                      {chat.participants.length} members
                    </p>
                  )}
                </div>
              </div>
            ))
          )}
        </div>
      </ScrollArea>
    </div>
  )
}