@armoyu/ui 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (182) hide show
  1. package/dist/app/api/proxy/[...path]/route.d.ts +22 -0
  2. package/dist/app/api/proxy/[...path]/route.d.ts.map +1 -0
  3. package/dist/app/api/proxy/[...path]/route.js +89 -0
  4. package/dist/app/api/proxy/[...path]/route.js.map +1 -0
  5. package/dist/app/layout.js +11 -11
  6. package/dist/components/Button.d.ts +7 -7
  7. package/dist/components/Button.js +15 -15
  8. package/dist/components/GenderStatsBar.d.ts +5 -5
  9. package/dist/components/GenderStatsBar.js +7 -7
  10. package/dist/components/RollingNumber.d.ts +6 -6
  11. package/dist/components/RollingNumber.js +23 -23
  12. package/dist/components/Slider.d.ts +10 -10
  13. package/dist/components/Slider.js +35 -35
  14. package/dist/components/StatsGrid.js +13 -13
  15. package/dist/components/ViewModeToggle.d.ts +7 -7
  16. package/dist/components/ViewModeToggle.js +9 -9
  17. package/dist/components/modules/auth/Dashboard.js +250 -250
  18. package/dist/components/modules/auth/MediaLightbox.d.ts +13 -13
  19. package/dist/components/modules/auth/MediaLightbox.js +46 -46
  20. package/dist/components/modules/auth/PostCard.js +112 -112
  21. package/dist/components/modules/auth/PostInteractionsModal.js +12 -12
  22. package/dist/components/modules/auth/RepostModal.js +75 -75
  23. package/dist/components/modules/auth/SidebarLeft.js +40 -40
  24. package/dist/components/modules/auth/Stories.js +15 -15
  25. package/dist/components/modules/auth/StoryViewer.js +47 -47
  26. package/dist/components/modules/chat/ChatContainer.js +196 -196
  27. package/dist/components/modules/chat/ChatInput.js +30 -30
  28. package/dist/components/modules/chat/ChatList.js +51 -51
  29. package/dist/components/modules/chat/ChatMessage.d.ts +11 -11
  30. package/dist/components/modules/chat/ChatMessage.js +6 -6
  31. package/dist/components/modules/chat/ChatNotes.js +11 -11
  32. package/dist/components/modules/community/GroupHeader.js +17 -17
  33. package/dist/components/modules/community/GroupMenu.js +16 -16
  34. package/dist/components/modules/community/SchoolCard.js +7 -7
  35. package/dist/components/modules/community/SurveyCard.js +35 -35
  36. package/dist/components/modules/forum/ForumBoard.d.ts +16 -16
  37. package/dist/components/modules/forum/ForumBoard.js +6 -6
  38. package/dist/components/modules/forum/ForumPost.d.ts +13 -13
  39. package/dist/components/modules/forum/ForumPost.js +5 -5
  40. package/dist/components/modules/forum/NewTopicModal.d.ts +7 -7
  41. package/dist/components/modules/forum/NewTopicModal.js +26 -26
  42. package/dist/components/modules/forum/TopicItem.d.ts +15 -15
  43. package/dist/components/modules/forum/TopicItem.js +6 -6
  44. package/dist/components/modules/galleries/GalleryCard.d.ts +9 -9
  45. package/dist/components/modules/galleries/GalleryCard.js +5 -5
  46. package/dist/components/modules/giveaways/GiveawayCard.d.ts +9 -9
  47. package/dist/components/modules/giveaways/GiveawayCard.js +6 -6
  48. package/dist/components/modules/groups/ApplicationModal.d.ts +7 -7
  49. package/dist/components/modules/groups/ApplicationModal.js +27 -27
  50. package/dist/components/modules/groups/GroupCard.d.ts +12 -12
  51. package/dist/components/modules/groups/GroupCard.js +6 -6
  52. package/dist/components/modules/guest/Introduction.js +13 -13
  53. package/dist/components/modules/magaza/BackToStore.js +10 -10
  54. package/dist/components/modules/magaza/StoreHeader.js +8 -8
  55. package/dist/components/modules/news/NewsCard.js +6 -6
  56. package/dist/components/modules/news/NewsComments.js +52 -52
  57. package/dist/components/modules/profile/CloudStorageModal.d.ts +8 -8
  58. package/dist/components/modules/profile/CloudStorageModal.js +31 -31
  59. package/dist/components/modules/profile/EditProfileModal.d.ts +8 -8
  60. package/dist/components/modules/profile/EditProfileModal.js +27 -27
  61. package/dist/components/modules/profile/ProfileContent.js +70 -70
  62. package/dist/components/modules/profile/ProfileHeader.js +19 -19
  63. package/dist/components/modules/profile/ProfileStats.d.ts +1 -1
  64. package/dist/components/modules/profile/ProfileStats.js +14 -14
  65. package/dist/components/modules/profile/TeamSelectorModal.js +16 -16
  66. package/dist/components/modules/stations/StationCard.js +25 -25
  67. package/dist/components/modules/stations/StationQRModal.js +12 -12
  68. package/dist/components/shared/FloatingChatButton.js +20 -20
  69. package/dist/components/shared/Footer.d.ts +1 -1
  70. package/dist/components/shared/Footer.js +9 -9
  71. package/dist/components/shared/Header.js +97 -97
  72. package/dist/components/shared/LoginModal.d.ts.map +1 -1
  73. package/dist/components/shared/LoginModal.js +12 -16
  74. package/dist/components/shared/LoginModal.js.map +1 -1
  75. package/dist/components/shared/MainLayoutWrapper.js +7 -7
  76. package/dist/components/shared/PageWidth.d.ts +5 -5
  77. package/dist/components/shared/PageWidth.js +13 -13
  78. package/dist/components/showcase/SocialTab.d.ts.map +1 -1
  79. package/dist/components/showcase/SocialTab.js +47 -2
  80. package/dist/components/showcase/SocialTab.js.map +1 -1
  81. package/dist/context/AuthContext.d.ts +1 -1
  82. package/dist/context/AuthContext.d.ts.map +1 -1
  83. package/dist/context/AuthContext.js +52 -33
  84. package/dist/context/AuthContext.js.map +1 -1
  85. package/dist/context/CartContext.js +63 -63
  86. package/dist/context/ChatContext.d.ts +12 -12
  87. package/dist/context/ChatContext.js +17 -17
  88. package/dist/context/LayoutContext.d.ts +10 -10
  89. package/dist/context/LayoutContext.js +16 -16
  90. package/dist/context/SocketContext.js +30 -30
  91. package/dist/context/ThemeContext.d.ts +10 -10
  92. package/dist/context/ThemeContext.js +39 -39
  93. package/dist/index.js +80 -80
  94. package/dist/lib/constants/educationData.js +117 -117
  95. package/dist/lib/constants/punishmentData.d.ts +29 -29
  96. package/dist/lib/constants/punishmentData.js +183 -183
  97. package/dist/lib/constants/seedData.js +694 -694
  98. package/dist/lib/constants/stationData.js +166 -166
  99. package/dist/lib/constants/surveyData.js +49 -49
  100. package/dist/lib/constants/teamData.js +65 -65
  101. package/dist/types/stats.d.ts +17 -17
  102. package/dist/types/stats.js +1 -1
  103. package/package.json +47 -46
  104. package/src/globals.css +187 -187
  105. package/next.config.ts +0 -13
  106. package/postcss.config.js +0 -6
  107. package/src/app/layout.tsx +0 -64
  108. package/src/app/page.tsx +0 -101
  109. package/src/components/Button.tsx +0 -41
  110. package/src/components/GenderStatsBar.tsx +0 -66
  111. package/src/components/RollingNumber.tsx +0 -50
  112. package/src/components/Slider.tsx +0 -114
  113. package/src/components/StatsGrid.tsx +0 -35
  114. package/src/components/ViewModeToggle.tsx +0 -39
  115. package/src/components/modules/auth/Dashboard.tsx +0 -649
  116. package/src/components/modules/auth/MediaLightbox.tsx +0 -112
  117. package/src/components/modules/auth/PostCard.tsx +0 -556
  118. package/src/components/modules/auth/PostInteractionsModal.tsx +0 -138
  119. package/src/components/modules/auth/RepostModal.tsx +0 -167
  120. package/src/components/modules/auth/SidebarLeft.tsx +0 -237
  121. package/src/components/modules/auth/Stories.tsx +0 -69
  122. package/src/components/modules/auth/StoryViewer.tsx +0 -146
  123. package/src/components/modules/chat/ChatContainer.tsx +0 -332
  124. package/src/components/modules/chat/ChatInput.tsx +0 -57
  125. package/src/components/modules/chat/ChatList.tsx +0 -179
  126. package/src/components/modules/chat/ChatMessage.tsx +0 -43
  127. package/src/components/modules/chat/ChatNotes.tsx +0 -58
  128. package/src/components/modules/community/GroupHeader.tsx +0 -111
  129. package/src/components/modules/community/GroupMenu.tsx +0 -82
  130. package/src/components/modules/community/SchoolCard.tsx +0 -104
  131. package/src/components/modules/community/SurveyCard.tsx +0 -149
  132. package/src/components/modules/forum/ForumBoard.tsx +0 -78
  133. package/src/components/modules/forum/ForumPost.tsx +0 -71
  134. package/src/components/modules/forum/NewTopicModal.tsx +0 -112
  135. package/src/components/modules/forum/TopicItem.tsx +0 -72
  136. package/src/components/modules/galleries/GalleryCard.tsx +0 -66
  137. package/src/components/modules/giveaways/GiveawayCard.tsx +0 -76
  138. package/src/components/modules/groups/ApplicationModal.tsx +0 -133
  139. package/src/components/modules/groups/GroupCard.tsx +0 -96
  140. package/src/components/modules/guest/Introduction.tsx +0 -60
  141. package/src/components/modules/magaza/BackToStore.tsx +0 -53
  142. package/src/components/modules/magaza/StoreHeader.tsx +0 -74
  143. package/src/components/modules/news/NewsCard.tsx +0 -66
  144. package/src/components/modules/news/NewsComments.tsx +0 -141
  145. package/src/components/modules/profile/CloudStorageModal.tsx +0 -200
  146. package/src/components/modules/profile/EditProfileModal.tsx +0 -191
  147. package/src/components/modules/profile/ProfileContent.tsx +0 -491
  148. package/src/components/modules/profile/ProfileHeader.tsx +0 -128
  149. package/src/components/modules/profile/ProfileStats.tsx +0 -72
  150. package/src/components/modules/profile/TeamSelectorModal.tsx +0 -129
  151. package/src/components/modules/stations/StationCard.tsx +0 -95
  152. package/src/components/modules/stations/StationQRModal.tsx +0 -102
  153. package/src/components/shared/FloatingChatButton.tsx +0 -57
  154. package/src/components/shared/Footer.tsx +0 -77
  155. package/src/components/shared/Header.tsx +0 -799
  156. package/src/components/shared/LoginModal.tsx +0 -208
  157. package/src/components/shared/MainLayoutWrapper.tsx +0 -15
  158. package/src/components/shared/PageWidth.tsx +0 -22
  159. package/src/components/showcase/CommunityTab.tsx +0 -22
  160. package/src/components/showcase/CorporateTab.tsx +0 -38
  161. package/src/components/showcase/GeneralTab.tsx +0 -41
  162. package/src/components/showcase/MessagesTab.tsx +0 -26
  163. package/src/components/showcase/ProfileTab.tsx +0 -20
  164. package/src/components/showcase/ShopTab.tsx +0 -24
  165. package/src/components/showcase/SocialTab.tsx +0 -28
  166. package/src/context/AuthContext.tsx +0 -104
  167. package/src/context/CartContext.tsx +0 -93
  168. package/src/context/ChatContext.tsx +0 -32
  169. package/src/context/LayoutContext.tsx +0 -29
  170. package/src/context/SocketContext.tsx +0 -50
  171. package/src/context/ThemeContext.tsx +0 -52
  172. package/src/index.ts +0 -96
  173. package/src/lib/constants/educationData.ts +0 -124
  174. package/src/lib/constants/punishmentData.ts +0 -201
  175. package/src/lib/constants/seedData.ts +0 -758
  176. package/src/lib/constants/stationData.ts +0 -170
  177. package/src/lib/constants/surveyData.ts +0 -53
  178. package/src/lib/constants/teamData.ts +0 -69
  179. package/src/lib/utils/numberFormat.ts +0 -16
  180. package/src/lib/utils/odpUtils.ts +0 -51
  181. package/src/types/index.ts +0 -1
  182. package/src/types/stats.ts +0 -17
@@ -1,197 +1,197 @@
1
- 'use client';
2
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
- import React, { useState, useEffect } from 'react';
4
- import { useAuth } from '../../../context/AuthContext';
5
- import { ChatList } from './ChatList';
6
- import { Chat, User, Session, ChatMessage as ChatMessageModel } from '@armoyu/core';
7
- import { ChatMessage } from './ChatMessage';
8
- import { ChatInput } from './ChatInput';
9
- import { useChat } from '../../../context/ChatContext';
10
- import { useSocket } from '../../../context/SocketContext';
11
- // Mock Data
12
- import { userList } from '../../../lib/constants/seedData';
13
- export function ChatContainer() {
14
- const { user, session, updateSession } = useAuth();
15
- const { closeChat } = useChat();
16
- const { emit, on, isConnected } = useSocket();
17
- // Eğer null ise liste görünümü açık, ID var ise mesajlaşma açık.
18
- const [activeContactId, setActiveContactId] = useState(null);
19
- const [localMessages, setLocalMessages] = useState([]);
20
- const [localContacts, setLocalContacts] = useState([]);
21
- const [isTyping, setIsTyping] = useState(false);
22
- const messagesEndRef = React.useRef(null);
23
- const scrollToBottom = () => {
24
- messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
25
- };
26
- // Scroll to bottom when messages or typing status changes
27
- useEffect(() => {
28
- scrollToBottom();
29
- }, [localMessages, isTyping]);
30
- // Sync with session's chatList (chatList lives on Session, not User)
31
- useEffect(() => {
32
- if (session?.chatList) {
33
- setLocalContacts(session.chatList);
34
- }
35
- }, [session?.chatList]);
36
- // Socket Connection for Real-time Messages & Typing
37
- useEffect(() => {
38
- const offMsg = on('message', (incomingMsg) => {
39
- console.log('[ChatContainer] Incoming socket message:', incomingMsg);
40
- const msgModel = new ChatMessageModel({
41
- id: incomingMsg.id,
42
- sender: incomingMsg.sender ? new User(incomingMsg.sender) : undefined,
43
- content: incomingMsg.content,
44
- timestamp: incomingMsg.timestamp,
45
- isSystem: incomingMsg.isSystem || false
46
- });
47
- // Update contacts list
48
- setLocalContacts(prev => {
49
- const contactId = incomingMsg.chatId || incomingMsg.sender?.username;
50
- const contactExists = prev.some(c => c.id === contactId);
51
- if (!contactExists && incomingMsg.sender?.username !== user?.username) {
52
- // CREATE NEW CHAT: If sender isn't in our list, create the chat box for them!
53
- const newChat = new Chat({
54
- id: contactId,
55
- name: incomingMsg.sender?.displayName || incomingMsg.sender?.username || 'Bilinmeyen',
56
- avatar: incomingMsg.sender?.avatar || '',
57
- lastMessage: msgModel,
58
- time: msgModel.timestamp,
59
- updatedAt: Date.now(),
60
- messages: [msgModel],
61
- unreadCount: (activeContactId !== contactId) ? 1 : 0,
62
- isOnline: true // Assume online since they just sent a message
63
- });
64
- // PERSIST to Session!
65
- if (session) {
66
- const updatedChatList = [newChat, ...(session.chatList || [])];
67
- updateSession(new Session({ ...session, chatList: updatedChatList }));
68
- }
69
- return [newChat, ...prev];
70
- }
71
- // UPDATE EXISTING CHAT
72
- return prev.map(c => {
73
- if (c.id === contactId) {
74
- // Only add if not already in messages to avoid duplicates from echo
75
- const messageExists = c.messages.some(m => m.id === msgModel.id);
76
- const updatedChat = new Chat({
77
- ...c,
78
- lastMessage: msgModel,
79
- time: msgModel.timestamp,
80
- updatedAt: Date.now(),
81
- messages: messageExists ? c.messages : [...(c.messages || []), msgModel],
82
- unreadCount: (activeContactId !== c.id && incomingMsg.sender?.username !== user?.username) ? c.unreadCount + 1 : c.unreadCount
83
- });
84
- // Note: We don't necessarily need to update the whole session on every message to avoid excessive renders,
85
- // as local state handles the UI. But for NEW chats, we must.
86
- return updatedChat;
87
- }
88
- return c;
89
- });
90
- });
91
- // If this is the active chat, update visible messages
92
- if (activeContactId === incomingMsg.chatId || activeContactId === incomingMsg.sender?.username) {
93
- setLocalMessages(prev => {
94
- if (prev.some(m => m.id === incomingMsg.id))
95
- return prev;
96
- return [...prev, msgModel];
97
- });
98
- setIsTyping(false); // Stop typing on message receive
99
- }
100
- });
101
- const offTyping = on('typing', (data) => {
102
- // console.log('[ChatContainer] Incoming typing event:', data);
103
- // If we are recipient (data.chatId is US) and the sender IS the one we are currently viewing
104
- const isChattingWithSender = data.username === activeContactId && data.chatId === user?.username;
105
- // Special case for system bot
106
- const isBotTyping = data.username === 'system' && data.chatId === user?.username;
107
- if (isChattingWithSender || isBotTyping) {
108
- setIsTyping(data.isTyping);
109
- }
110
- });
111
- return () => {
112
- offMsg();
113
- offTyping();
114
- };
115
- }, [on, activeContactId, user?.username]);
116
- const handleSelectContact = (id) => {
117
- // Check if the contact is already in our list
118
- let contact = localContacts.find((c) => c.id === id);
119
- // If NOT in our list (clicked from "New Contacts" search), we must create it!
120
- if (!contact) {
121
- const newUser = userList.find((u) => u.username === id);
122
- if (newUser) {
123
- contact = new Chat({
124
- id: newUser.username,
125
- name: newUser.displayName,
126
- avatar: newUser.avatar,
127
- updatedAt: Date.now(),
128
- messages: [],
129
- isOnline: true, // Mock online status for now
130
- unreadCount: 0
131
- });
132
- const updatedContacts = [contact, ...localContacts];
133
- setLocalContacts(updatedContacts);
134
- // Persist to session so it stays in the list!
135
- if (session) {
136
- const updatedChatList = [contact, ...(session.chatList || [])];
137
- updateSession(new Session({ ...session, chatList: updatedChatList }));
138
- }
139
- }
140
- }
141
- setActiveContactId(id);
142
- setLocalMessages(contact?.messages || []);
143
- setIsTyping(false);
144
- // Clear unread on select (if it was an existing contact)
145
- if (contact && contact.unreadCount > 0) {
146
- setLocalContacts(prev => prev.map(c => c.id === id ? { ...c, unreadCount: 0 } : c));
147
- }
148
- };
149
- const handleSendMessage = (text) => {
150
- if (!text.trim() || !activeContactId)
151
- return;
152
- const messageData = {
153
- id: Date.now().toString(),
154
- chatId: activeContactId,
155
- sender: {
156
- username: user?.username,
157
- displayName: user?.displayName,
158
- avatar: user?.avatar
159
- },
160
- content: text,
161
- timestamp: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }),
162
- };
163
- // Update local state immediately for instant feedback
164
- const newMessage = new ChatMessageModel({
165
- id: messageData.id,
166
- sender: user || undefined,
167
- content: text,
168
- timestamp: messageData.timestamp,
169
- isSystem: false
170
- });
171
- setLocalMessages(prev => [...prev, newMessage]);
172
- setLocalContacts(prev => prev.map(c => {
173
- if (c.id === activeContactId) {
174
- return new Chat({
175
- ...c,
176
- lastMessage: newMessage,
177
- time: newMessage.timestamp,
178
- updatedAt: Date.now(),
179
- messages: [...(c.messages || []), newMessage]
180
- });
181
- }
182
- return c;
183
- }));
184
- // Emit via socket for others
185
- emit('message', messageData);
186
- };
187
- if (!user) {
188
- return (_jsx("div", { className: "flex items-center justify-center h-full text-armoyu-text-muted bg-armoyu-card-bg rounded-3xl border border-gray-200 dark:border-white/10", children: "Sohbetleri g\u00F6rmek i\u00E7in giri\u015F yapmal\u0131s\u0131n\u0131z." }));
189
- }
190
- const activeContact = activeContactId ? localContacts.find((c) => c.id === activeContactId) : null;
191
- return (_jsxs("div", { className: "flex h-full w-full bg-armoyu-header-bg overflow-hidden relative z-10", children: [!activeContactId && (_jsx("div", { className: "w-full h-full flex flex-col animate-in fade-in slide-in-from-left-4 duration-300", children: _jsx(ChatList, { contacts: localContacts, activeId: '', onSelect: handleSelectContact }) })), activeContactId && activeContact && (_jsxs("div", { className: "w-full h-full flex flex-col bg-armoyu-bg relative animate-in fade-in slide-in-from-right-4 duration-300", children: [_jsxs("div", { className: "h-[76px] border-b border-gray-200 dark:border-white/5 bg-armoyu-card-bg flex items-center px-4 gap-3 z-10 shrink-0", children: [_jsx("button", { onClick: () => setActiveContactId(null), className: "p-2 -ml-2 text-armoyu-text-muted hover:text-armoyu-text hover:bg-black/5 dark:hover:bg-white/5 transition-colors rounded-full focus:outline-none", children: _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "28", height: "28", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: _jsx("polyline", { points: "15 18 9 12 15 6" }) }) }), _jsx("img", { src: activeContact.avatar, className: "w-10 h-10 rounded-full border border-black/5 dark:border-white/10 shadow-sm", alt: "" }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("h3", { className: "font-bold text-armoyu-text truncate text-base", children: activeContact.name }), _jsx("div", { className: "flex items-center gap-1.5 mt-0.5", children: activeContact.isOnline ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "w-2 h-2 rounded-full bg-emerald-500 shadow-[0_0_5px_rgba(16,185,129,0.6)] animate-pulse" }), _jsx("span", { className: "text-xs font-bold text-emerald-500 shadow-sm", children: "\u00C7evrimi\u00E7i" })] })) : (_jsxs(_Fragment, { children: [_jsx("span", { className: "w-2 h-2 rounded-full bg-gray-400 dark:bg-gray-600" }), _jsxs("span", { className: "text-xs font-bold text-armoyu-text-muted", children: ["Son g\u00F6r\u00FClme ", activeContact.lastSeen] })] })) })] }), _jsxs("div", { className: "flex gap-1", children: [_jsx("button", { className: "p-2 text-armoyu-text-muted hover:text-blue-500 rounded-full hover:bg-blue-500/10 transition-colors", title: "Ara", children: _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z" }) }) }), _jsx("button", { onClick: closeChat, className: "p-2 text-armoyu-text-muted hover:text-red-500 rounded-full hover:bg-red-500/10 transition-colors", title: "Sohbeti Kapat", children: _jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), _jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }) })] })] }), _jsxs("div", { className: "flex-1 overflow-y-auto p-4 md:p-6 space-y-2 relative hide-scrollbar", children: [_jsx("div", { className: "text-center mb-8", children: _jsx("span", { className: "inline-block bg-black/5 dark:bg-white/5 text-armoyu-text-muted text-xs font-bold px-3 py-1 rounded-full border border-black/5 dark:border-white/5", children: "Bug\u00FCn" }) }), localMessages.map(msg => (_jsx(ChatMessage, { id: msg.id, sender: {
192
- name: msg.sender?.displayName || 'Bilinmiyor',
193
- avatar: msg.sender?.avatar || '',
194
- isSelf: msg.sender?.username === user?.username
195
- }, content: msg.content, timestamp: msg.timestamp }, msg.id))), isTyping && (_jsx("div", { className: "flex gap-2 items-center px-4 animate-in fade-in slide-in-from-bottom-2 duration-300", children: _jsxs("div", { className: "flex gap-1 items-center bg-black/5 dark:bg-white/5 px-3 py-1.5 rounded-2xl border border-black/5 dark:border-white/5", children: [_jsxs("div", { className: "flex gap-0.5 mt-0.5", children: [_jsx("span", { className: "w-1 h-1 rounded-full bg-blue-500 animate-bounce [animation-delay:-0.3s]" }), _jsx("span", { className: "w-1 h-1 rounded-full bg-blue-500 animate-bounce [animation-delay:-0.15s]" }), _jsx("span", { className: "w-1 h-1 rounded-full bg-blue-500 animate-bounce" })] }), _jsx("span", { className: "text-[10px] font-bold text-armoyu-text-muted italic ml-1", children: "Yaz\u0131yor..." })] }) })), _jsx("div", { ref: messagesEndRef, className: "h-2" })] }), _jsx(ChatInput, { onSend: handleSendMessage, chatId: activeContactId })] }))] }));
196
- }
1
+ 'use client';
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import React, { useState, useEffect } from 'react';
4
+ import { useAuth } from '../../../context/AuthContext';
5
+ import { ChatList } from './ChatList';
6
+ import { Chat, User, Session, ChatMessage as ChatMessageModel } from '@armoyu/core';
7
+ import { ChatMessage } from './ChatMessage';
8
+ import { ChatInput } from './ChatInput';
9
+ import { useChat } from '../../../context/ChatContext';
10
+ import { useSocket } from '../../../context/SocketContext';
11
+ // Mock Data
12
+ import { userList } from '../../../lib/constants/seedData';
13
+ export function ChatContainer() {
14
+ const { user, session, updateSession } = useAuth();
15
+ const { closeChat } = useChat();
16
+ const { emit, on, isConnected } = useSocket();
17
+ // Eğer null ise liste görünümü açık, ID var ise mesajlaşma açık.
18
+ const [activeContactId, setActiveContactId] = useState(null);
19
+ const [localMessages, setLocalMessages] = useState([]);
20
+ const [localContacts, setLocalContacts] = useState([]);
21
+ const [isTyping, setIsTyping] = useState(false);
22
+ const messagesEndRef = React.useRef(null);
23
+ const scrollToBottom = () => {
24
+ messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
25
+ };
26
+ // Scroll to bottom when messages or typing status changes
27
+ useEffect(() => {
28
+ scrollToBottom();
29
+ }, [localMessages, isTyping]);
30
+ // Sync with session's chatList (chatList lives on Session, not User)
31
+ useEffect(() => {
32
+ if (session?.chatList) {
33
+ setLocalContacts(session.chatList);
34
+ }
35
+ }, [session?.chatList]);
36
+ // Socket Connection for Real-time Messages & Typing
37
+ useEffect(() => {
38
+ const offMsg = on('message', (incomingMsg) => {
39
+ console.log('[ChatContainer] Incoming socket message:', incomingMsg);
40
+ const msgModel = new ChatMessageModel({
41
+ id: incomingMsg.id,
42
+ sender: incomingMsg.sender ? new User(incomingMsg.sender) : undefined,
43
+ content: incomingMsg.content,
44
+ timestamp: incomingMsg.timestamp,
45
+ isSystem: incomingMsg.isSystem || false
46
+ });
47
+ // Update contacts list
48
+ setLocalContacts(prev => {
49
+ const contactId = incomingMsg.chatId || incomingMsg.sender?.username;
50
+ const contactExists = prev.some(c => c.id === contactId);
51
+ if (!contactExists && incomingMsg.sender?.username !== user?.username) {
52
+ // CREATE NEW CHAT: If sender isn't in our list, create the chat box for them!
53
+ const newChat = new Chat({
54
+ id: contactId,
55
+ name: incomingMsg.sender?.displayName || incomingMsg.sender?.username || 'Bilinmeyen',
56
+ avatar: incomingMsg.sender?.avatar || '',
57
+ lastMessage: msgModel,
58
+ time: msgModel.timestamp,
59
+ updatedAt: Date.now(),
60
+ messages: [msgModel],
61
+ unreadCount: (activeContactId !== contactId) ? 1 : 0,
62
+ isOnline: true // Assume online since they just sent a message
63
+ });
64
+ // PERSIST to Session!
65
+ if (session) {
66
+ const updatedChatList = [newChat, ...(session.chatList || [])];
67
+ updateSession(new Session({ ...session, chatList: updatedChatList }));
68
+ }
69
+ return [newChat, ...prev];
70
+ }
71
+ // UPDATE EXISTING CHAT
72
+ return prev.map(c => {
73
+ if (c.id === contactId) {
74
+ // Only add if not already in messages to avoid duplicates from echo
75
+ const messageExists = c.messages.some(m => m.id === msgModel.id);
76
+ const updatedChat = new Chat({
77
+ ...c,
78
+ lastMessage: msgModel,
79
+ time: msgModel.timestamp,
80
+ updatedAt: Date.now(),
81
+ messages: messageExists ? c.messages : [...(c.messages || []), msgModel],
82
+ unreadCount: (activeContactId !== c.id && incomingMsg.sender?.username !== user?.username) ? c.unreadCount + 1 : c.unreadCount
83
+ });
84
+ // Note: We don't necessarily need to update the whole session on every message to avoid excessive renders,
85
+ // as local state handles the UI. But for NEW chats, we must.
86
+ return updatedChat;
87
+ }
88
+ return c;
89
+ });
90
+ });
91
+ // If this is the active chat, update visible messages
92
+ if (activeContactId === incomingMsg.chatId || activeContactId === incomingMsg.sender?.username) {
93
+ setLocalMessages(prev => {
94
+ if (prev.some(m => m.id === incomingMsg.id))
95
+ return prev;
96
+ return [...prev, msgModel];
97
+ });
98
+ setIsTyping(false); // Stop typing on message receive
99
+ }
100
+ });
101
+ const offTyping = on('typing', (data) => {
102
+ // console.log('[ChatContainer] Incoming typing event:', data);
103
+ // If we are recipient (data.chatId is US) and the sender IS the one we are currently viewing
104
+ const isChattingWithSender = data.username === activeContactId && data.chatId === user?.username;
105
+ // Special case for system bot
106
+ const isBotTyping = data.username === 'system' && data.chatId === user?.username;
107
+ if (isChattingWithSender || isBotTyping) {
108
+ setIsTyping(data.isTyping);
109
+ }
110
+ });
111
+ return () => {
112
+ offMsg();
113
+ offTyping();
114
+ };
115
+ }, [on, activeContactId, user?.username]);
116
+ const handleSelectContact = (id) => {
117
+ // Check if the contact is already in our list
118
+ let contact = localContacts.find((c) => c.id === id);
119
+ // If NOT in our list (clicked from "New Contacts" search), we must create it!
120
+ if (!contact) {
121
+ const newUser = userList.find((u) => u.username === id);
122
+ if (newUser) {
123
+ contact = new Chat({
124
+ id: newUser.username,
125
+ name: newUser.displayName,
126
+ avatar: newUser.avatar,
127
+ updatedAt: Date.now(),
128
+ messages: [],
129
+ isOnline: true, // Mock online status for now
130
+ unreadCount: 0
131
+ });
132
+ const updatedContacts = [contact, ...localContacts];
133
+ setLocalContacts(updatedContacts);
134
+ // Persist to session so it stays in the list!
135
+ if (session) {
136
+ const updatedChatList = [contact, ...(session.chatList || [])];
137
+ updateSession(new Session({ ...session, chatList: updatedChatList }));
138
+ }
139
+ }
140
+ }
141
+ setActiveContactId(id);
142
+ setLocalMessages(contact?.messages || []);
143
+ setIsTyping(false);
144
+ // Clear unread on select (if it was an existing contact)
145
+ if (contact && contact.unreadCount > 0) {
146
+ setLocalContacts(prev => prev.map(c => c.id === id ? { ...c, unreadCount: 0 } : c));
147
+ }
148
+ };
149
+ const handleSendMessage = (text) => {
150
+ if (!text.trim() || !activeContactId)
151
+ return;
152
+ const messageData = {
153
+ id: Date.now().toString(),
154
+ chatId: activeContactId,
155
+ sender: {
156
+ username: user?.username,
157
+ displayName: user?.displayName,
158
+ avatar: user?.avatar
159
+ },
160
+ content: text,
161
+ timestamp: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }),
162
+ };
163
+ // Update local state immediately for instant feedback
164
+ const newMessage = new ChatMessageModel({
165
+ id: messageData.id,
166
+ sender: user || undefined,
167
+ content: text,
168
+ timestamp: messageData.timestamp,
169
+ isSystem: false
170
+ });
171
+ setLocalMessages(prev => [...prev, newMessage]);
172
+ setLocalContacts(prev => prev.map(c => {
173
+ if (c.id === activeContactId) {
174
+ return new Chat({
175
+ ...c,
176
+ lastMessage: newMessage,
177
+ time: newMessage.timestamp,
178
+ updatedAt: Date.now(),
179
+ messages: [...(c.messages || []), newMessage]
180
+ });
181
+ }
182
+ return c;
183
+ }));
184
+ // Emit via socket for others
185
+ emit('message', messageData);
186
+ };
187
+ if (!user) {
188
+ return (_jsx("div", { className: "flex items-center justify-center h-full text-armoyu-text-muted bg-armoyu-card-bg rounded-3xl border border-gray-200 dark:border-white/10", children: "Sohbetleri g\u00F6rmek i\u00E7in giri\u015F yapmal\u0131s\u0131n\u0131z." }));
189
+ }
190
+ const activeContact = activeContactId ? localContacts.find((c) => c.id === activeContactId) : null;
191
+ return (_jsxs("div", { className: "flex h-full w-full bg-armoyu-header-bg overflow-hidden relative z-10", children: [!activeContactId && (_jsx("div", { className: "w-full h-full flex flex-col animate-in fade-in slide-in-from-left-4 duration-300", children: _jsx(ChatList, { contacts: localContacts, activeId: '', onSelect: handleSelectContact }) })), activeContactId && activeContact && (_jsxs("div", { className: "w-full h-full flex flex-col bg-armoyu-bg relative animate-in fade-in slide-in-from-right-4 duration-300", children: [_jsxs("div", { className: "h-[76px] border-b border-gray-200 dark:border-white/5 bg-armoyu-card-bg flex items-center px-4 gap-3 z-10 shrink-0", children: [_jsx("button", { onClick: () => setActiveContactId(null), className: "p-2 -ml-2 text-armoyu-text-muted hover:text-armoyu-text hover:bg-black/5 dark:hover:bg-white/5 transition-colors rounded-full focus:outline-none", children: _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "28", height: "28", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: _jsx("polyline", { points: "15 18 9 12 15 6" }) }) }), _jsx("img", { src: activeContact.avatar, className: "w-10 h-10 rounded-full border border-black/5 dark:border-white/10 shadow-sm", alt: "" }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("h3", { className: "font-bold text-armoyu-text truncate text-base", children: activeContact.name }), _jsx("div", { className: "flex items-center gap-1.5 mt-0.5", children: activeContact.isOnline ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "w-2 h-2 rounded-full bg-emerald-500 shadow-[0_0_5px_rgba(16,185,129,0.6)] animate-pulse" }), _jsx("span", { className: "text-xs font-bold text-emerald-500 shadow-sm", children: "\u00C7evrimi\u00E7i" })] })) : (_jsxs(_Fragment, { children: [_jsx("span", { className: "w-2 h-2 rounded-full bg-gray-400 dark:bg-gray-600" }), _jsxs("span", { className: "text-xs font-bold text-armoyu-text-muted", children: ["Son g\u00F6r\u00FClme ", activeContact.lastSeen] })] })) })] }), _jsxs("div", { className: "flex gap-1", children: [_jsx("button", { className: "p-2 text-armoyu-text-muted hover:text-blue-500 rounded-full hover:bg-blue-500/10 transition-colors", title: "Ara", children: _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z" }) }) }), _jsx("button", { onClick: closeChat, className: "p-2 text-armoyu-text-muted hover:text-red-500 rounded-full hover:bg-red-500/10 transition-colors", title: "Sohbeti Kapat", children: _jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), _jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }) })] })] }), _jsxs("div", { className: "flex-1 overflow-y-auto p-4 md:p-6 space-y-2 relative hide-scrollbar", children: [_jsx("div", { className: "text-center mb-8", children: _jsx("span", { className: "inline-block bg-black/5 dark:bg-white/5 text-armoyu-text-muted text-xs font-bold px-3 py-1 rounded-full border border-black/5 dark:border-white/5", children: "Bug\u00FCn" }) }), localMessages.map(msg => (_jsx(ChatMessage, { id: msg.id, sender: {
192
+ name: msg.sender?.displayName || 'Bilinmiyor',
193
+ avatar: msg.sender?.avatar || '',
194
+ isSelf: msg.sender?.username === user?.username
195
+ }, content: msg.content, timestamp: msg.timestamp }, msg.id))), isTyping && (_jsx("div", { className: "flex gap-2 items-center px-4 animate-in fade-in slide-in-from-bottom-2 duration-300", children: _jsxs("div", { className: "flex gap-1 items-center bg-black/5 dark:bg-white/5 px-3 py-1.5 rounded-2xl border border-black/5 dark:border-white/5", children: [_jsxs("div", { className: "flex gap-0.5 mt-0.5", children: [_jsx("span", { className: "w-1 h-1 rounded-full bg-blue-500 animate-bounce [animation-delay:-0.3s]" }), _jsx("span", { className: "w-1 h-1 rounded-full bg-blue-500 animate-bounce [animation-delay:-0.15s]" }), _jsx("span", { className: "w-1 h-1 rounded-full bg-blue-500 animate-bounce" })] }), _jsx("span", { className: "text-[10px] font-bold text-armoyu-text-muted italic ml-1", children: "Yaz\u0131yor..." })] }) })), _jsx("div", { ref: messagesEndRef, className: "h-2" })] }), _jsx(ChatInput, { onSend: handleSendMessage, chatId: activeContactId })] }))] }));
196
+ }
197
197
  //# sourceMappingURL=ChatContainer.js.map
@@ -1,31 +1,31 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useState } from 'react';
3
- import { Button } from '../../Button';
4
- import { useSocket } from '../../../context/SocketContext';
5
- export function ChatInput({ onSend, chatId }) {
6
- const [text, setText] = useState('');
7
- const { emit } = useSocket();
8
- const handleSend = (e) => {
9
- e.preventDefault();
10
- if (text.trim()) {
11
- onSend(text);
12
- setText('');
13
- if (chatId)
14
- emit('typing', { chatId, isTyping: false });
15
- }
16
- };
17
- const handleChange = (val) => {
18
- setText(val);
19
- if (chatId) {
20
- const isTyping = val.length > 0;
21
- // Include username to help receiver filter out self
22
- emit('typing', {
23
- chatId,
24
- isTyping,
25
- username: typeof window !== 'undefined' ? localStorage.getItem('armoyu_username') : undefined
26
- });
27
- }
28
- };
29
- return (_jsxs("form", { onSubmit: handleSend, className: "p-3 border-t border-gray-200 dark:border-white/5 flex items-center gap-3 bg-armoyu-card-bg", children: [_jsx("button", { type: "button", className: "text-gray-400 hover:text-blue-500 p-2 transition-colors shrink-0", children: _jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("circle", { cx: "12", cy: "12", r: "10" }), _jsx("path", { d: "M8 14s1.5 2 4 2 4-2 4-2" }), _jsx("line", { x1: "9", y1: "9", x2: "9.01", y2: "9" }), _jsx("line", { x1: "15", y1: "9", x2: "15.01", y2: "9" })] }) }), _jsx("button", { type: "button", className: "text-gray-400 hover:text-blue-500 p-2 transition-colors hidden sm:block shrink-0", children: _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48" }) }) }), _jsx("input", { type: "text", value: text, onChange: (e) => handleChange(e.target.value), placeholder: "Bir mesaj yaz\u0131n...", className: "flex-1 min-w-0 bg-black/5 dark:bg-black/40 border border-black/10 dark:border-white/10 rounded-full px-4 py-2.5 text-sm text-armoyu-text placeholder-armoyu-text-muted focus:outline-none focus:border-blue-500 focus:ring-1 focus:ring-blue-500 transition-all shadow-inner" }), _jsx(Button, { variant: "primary", className: "rounded-full w-10 h-10 p-0 flex items-center justify-center shadow-[0_0_15px_rgba(37,99,235,0.3)] shrink-0 group", children: _jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", className: "translate-x-0.5 group-hover:translate-x-1 group-hover:-translate-y-0.5 transition-transform", children: [_jsx("line", { x1: "22", y1: "2", x2: "11", y2: "13" }), _jsx("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })] }) })] }));
30
- }
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import { Button } from '../../Button';
4
+ import { useSocket } from '../../../context/SocketContext';
5
+ export function ChatInput({ onSend, chatId }) {
6
+ const [text, setText] = useState('');
7
+ const { emit } = useSocket();
8
+ const handleSend = (e) => {
9
+ e.preventDefault();
10
+ if (text.trim()) {
11
+ onSend(text);
12
+ setText('');
13
+ if (chatId)
14
+ emit('typing', { chatId, isTyping: false });
15
+ }
16
+ };
17
+ const handleChange = (val) => {
18
+ setText(val);
19
+ if (chatId) {
20
+ const isTyping = val.length > 0;
21
+ // Include username to help receiver filter out self
22
+ emit('typing', {
23
+ chatId,
24
+ isTyping,
25
+ username: typeof window !== 'undefined' ? localStorage.getItem('armoyu_username') : undefined
26
+ });
27
+ }
28
+ };
29
+ return (_jsxs("form", { onSubmit: handleSend, className: "p-3 border-t border-gray-200 dark:border-white/5 flex items-center gap-3 bg-armoyu-card-bg", children: [_jsx("button", { type: "button", className: "text-gray-400 hover:text-blue-500 p-2 transition-colors shrink-0", children: _jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("circle", { cx: "12", cy: "12", r: "10" }), _jsx("path", { d: "M8 14s1.5 2 4 2 4-2 4-2" }), _jsx("line", { x1: "9", y1: "9", x2: "9.01", y2: "9" }), _jsx("line", { x1: "15", y1: "9", x2: "15.01", y2: "9" })] }) }), _jsx("button", { type: "button", className: "text-gray-400 hover:text-blue-500 p-2 transition-colors hidden sm:block shrink-0", children: _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48" }) }) }), _jsx("input", { type: "text", value: text, onChange: (e) => handleChange(e.target.value), placeholder: "Bir mesaj yaz\u0131n...", className: "flex-1 min-w-0 bg-black/5 dark:bg-black/40 border border-black/10 dark:border-white/10 rounded-full px-4 py-2.5 text-sm text-armoyu-text placeholder-armoyu-text-muted focus:outline-none focus:border-blue-500 focus:ring-1 focus:ring-blue-500 transition-all shadow-inner" }), _jsx(Button, { variant: "primary", className: "rounded-full w-10 h-10 p-0 flex items-center justify-center shadow-[0_0_15px_rgba(37,99,235,0.3)] shrink-0 group", children: _jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", className: "translate-x-0.5 group-hover:translate-x-1 group-hover:-translate-y-0.5 transition-transform", children: [_jsx("line", { x1: "22", y1: "2", x2: "11", y2: "13" }), _jsx("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })] }) })] }));
30
+ }
31
31
  //# sourceMappingURL=ChatInput.js.map
@@ -1,52 +1,52 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useChat } from '../../../context/ChatContext';
3
- import { useSocket } from '../../../context/SocketContext';
4
- import { ChatNotes } from './ChatNotes';
5
- import { useState } from 'react';
6
- import { userList } from '../../../lib/constants/seedData';
7
- import { useAuth } from '../../../context/AuthContext';
8
- export function ChatList({ contacts, activeId, onSelect }) {
9
- const { user } = useAuth();
10
- const { closeChat } = useChat();
11
- const { isConnected } = useSocket();
12
- const [searchQuery, setSearchQuery] = useState('');
13
- const [activeFilter, setActiveFilter] = useState('all');
14
- const filteredActiveContacts = contacts
15
- .filter(c => {
16
- // 1. Search Query Filter
17
- const matchesSearch = c.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
18
- (c.lastMessage?.content || '').toLowerCase().includes(searchQuery.toLowerCase());
19
- if (!matchesSearch)
20
- return false;
21
- // 2. Category Filter
22
- if (activeFilter === 'unread')
23
- return c.unreadCount > 0;
24
- if (activeFilter === 'favorites')
25
- return c.isFavorite;
26
- if (activeFilter === 'groups')
27
- return c.isGroup;
28
- return true; // 'all'
29
- })
30
- .sort((a, b) => (b.updatedAt || 0) - (a.updatedAt || 0));
31
- // 3. New Contact Search (Only when searching)
32
- const additionalContacts = searchQuery.length >= 2
33
- ? userList.filter((u) => {
34
- const matchesSearch = u.displayName.toLowerCase().includes(searchQuery.toLowerCase()) ||
35
- u.username.toLowerCase().includes(searchQuery.toLowerCase());
36
- const isNotSelf = u.username !== user?.username;
37
- const notInContacts = !contacts.some(c => c.id === u.username);
38
- return matchesSearch && isNotSelf && notInContacts;
39
- }).slice(0, 10)
40
- : [];
41
- return (_jsxs("div", { className: "w-full h-full flex flex-col bg-armoyu-bg border-r border-gray-200 dark:border-white/5", children: [_jsxs("div", { className: "p-4 md:p-5 border-b border-gray-200 dark:border-white/5", children: [_jsxs("div", { className: "flex justify-between items-center", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("h2", { className: "text-xl font-bold text-armoyu-text tracking-tight flex items-center gap-2", children: "Sohbetler" }), _jsxs("div", { className: "flex items-center gap-1.5 px-2 py-0.5 rounded-full bg-black/5 dark:bg-white/5 border border-black/5 dark:border-white/5", children: [_jsx("div", { className: `w-1.5 h-1.5 rounded-full ${isConnected ? 'bg-emerald-500 shadow-[0_0_5px_rgba(16,185,129,0.8)]' : 'bg-red-500'} animate-pulse` }), _jsx("span", { className: "text-[10px] font-black text-armoyu-text-muted uppercase tracking-tighter", children: isConnected ? 'Sockete Bağlı' : 'Bağlanıyor...' })] })] }), _jsx("button", { onClick: closeChat, className: "p-2 -mr-2 text-armoyu-text-muted hover:text-red-500 hover:bg-red-500/10 transition-colors rounded-full", title: "Sohbeti Kapat", children: _jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), _jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }) })] }), _jsxs("div", { className: "relative mt-4", children: [_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", className: "absolute left-3 top-1/2 -translate-y-1/2 text-gray-500", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("circle", { cx: "11", cy: "11", r: "8" }), _jsx("line", { x1: "21", y1: "21", x2: "16.65", y2: "16.65" })] }), _jsx("input", { type: "text", placeholder: "Ki\u015Fi ara...", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), className: "w-full bg-white/5 dark:bg-black/20 border border-black/10 dark:border-white/10 rounded-xl pl-10 pr-4 py-2.5 text-sm text-slate-900 dark:text-white placeholder-gray-500 hover:border-black/20 dark:hover:border-white/20 focus:outline-none focus:border-blue-500 transition-all" })] })] }), _jsx(ChatNotes, {}), _jsx("div", { className: "px-4 pb-4 flex gap-2 overflow-x-auto no-scrollbar shrink-0", children: [
42
- { id: 'all', label: 'Tümü' },
43
- { id: 'unread', label: 'Okunmamış' },
44
- { id: 'favorites', label: 'Favoriler' },
45
- { id: 'groups', label: 'Gruplar' }
46
- ].map((filter) => (_jsx("button", { onClick: () => setActiveFilter(filter.id), className: `px-4 py-2 rounded-xl text-xs font-black transition-all whitespace-nowrap border ${activeFilter === filter.id
47
- ? 'bg-blue-500 text-white border-blue-500 shadow-md shadow-blue-500/20 scale-105'
48
- : 'bg-black/5 dark:bg-white/5 text-armoyu-text-muted border-transparent hover:bg-black/10 dark:hover:bg-white/10'}`, children: filter.label }, filter.id))) }), _jsxs("div", { className: "flex-1 overflow-y-auto no-scrollbar p-3 space-y-1.5", children: [_jsxs("div", { className: "space-y-1.5", children: [searchQuery.length > 0 && filteredActiveContacts.length > 0 && (_jsx("div", { className: "px-3 py-1 text-[10px] font-black text-armoyu-text-muted uppercase tracking-[0.2em] opacity-50", children: "Sohbet Ge\u00E7mi\u015Fi" })), filteredActiveContacts.map(c => (_jsxs("button", { onClick: () => onSelect(c.id), className: `w-full flex items-center gap-4 p-3 rounded-2xl transition-all cursor-pointer text-left ${activeId === c.id
49
- ? 'bg-blue-500/10 dark:bg-blue-500/20 border border-blue-500/20 shadow-inner'
50
- : 'hover:bg-black/5 dark:hover:bg-white/5 border border-transparent'}`, children: [_jsxs("div", { className: "relative shrink-0", children: [_jsx("img", { src: c.avatar, alt: c.name, className: "w-12 h-12 rounded-full object-cover border border-white/10 shadow-sm" }), c.isOnline && (_jsx("div", { className: "absolute -bottom-0.5 -right-0.5 w-3.5 h-3.5 bg-green-500 rounded-full border-2 border-white dark:border-[#0a0a0e] shadow-sm" }))] }), _jsxs("div", { className: "flex-1 overflow-hidden", children: [_jsxs("div", { className: "flex justify-between items-center mb-1", children: [_jsx("span", { className: "font-black text-slate-900 dark:text-gray-200 text-sm truncate max-w-[130px]", children: c.name }), _jsx("span", { className: "text-xs text-gray-500 font-black", children: c.time })] }), _jsxs("div", { className: "flex justify-between items-center", children: [_jsx("span", { className: `text-xs truncate max-w-[120px] font-bold ${c.unreadCount > 0 ? 'text-slate-950 dark:text-white' : 'text-slate-500'}`, children: c.lastMessage?.content || 'Mesaj yok' }), c.unreadCount > 0 && (_jsx("span", { className: "bg-blue-500 text-white text-[10px] font-black px-1.5 py-0.5 rounded-md leading-none shadow-md animate-in zoom-in duration-300", children: c.unreadCount > 9 ? '9+' : c.unreadCount }))] })] })] }, c.id)))] }), additionalContacts.length > 0 && (_jsxs("div", { className: "space-y-1.5 mt-6 animate-in fade-in slide-in-from-top-2 duration-500", children: [_jsx("div", { className: "px-3 py-1 text-[10px] font-black text-blue-500 uppercase tracking-[0.2em]", children: "Yeni Sohbet Ba\u015Flat" }), additionalContacts.map((u) => (_jsxs("button", { onClick: () => onSelect(u.username), className: "w-full flex items-center gap-4 p-3 rounded-2xl hover:bg-white/5 border border-transparent transition-all group", children: [_jsx("div", { className: "relative shrink-0", children: _jsx("img", { src: u.avatar, alt: u.displayName, className: "w-12 h-12 rounded-full object-cover border border-white/10 shadow-sm opacity-60 group-hover:opacity-100 transition-opacity" }) }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("div", { className: "font-black text-slate-900 dark:text-gray-200 text-sm truncate", children: u.displayName }), _jsxs("div", { className: "text-[10px] font-bold text-armoyu-text-muted uppercase tracking-tighter", children: ["@", u.username] })] }), _jsx("div", { className: "w-8 h-8 rounded-full bg-blue-500/10 flex items-center justify-center text-blue-500 scale-0 group-hover:scale-100 transition-all duration-300", children: _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: _jsx("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" }) }) })] }, u.username)))] })), searchQuery.length > 0 && filteredActiveContacts.length === 0 && additionalContacts.length === 0 && (_jsx("div", { className: "py-12 text-center", children: _jsx("div", { className: "text-armoyu-text-muted text-sm font-bold opacity-30", children: "Sonu\u00E7 bulunamad\u0131" }) }))] })] }));
51
- }
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useChat } from '../../../context/ChatContext';
3
+ import { useSocket } from '../../../context/SocketContext';
4
+ import { ChatNotes } from './ChatNotes';
5
+ import { useState } from 'react';
6
+ import { userList } from '../../../lib/constants/seedData';
7
+ import { useAuth } from '../../../context/AuthContext';
8
+ export function ChatList({ contacts, activeId, onSelect }) {
9
+ const { user } = useAuth();
10
+ const { closeChat } = useChat();
11
+ const { isConnected } = useSocket();
12
+ const [searchQuery, setSearchQuery] = useState('');
13
+ const [activeFilter, setActiveFilter] = useState('all');
14
+ const filteredActiveContacts = contacts
15
+ .filter(c => {
16
+ // 1. Search Query Filter
17
+ const matchesSearch = c.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
18
+ (c.lastMessage?.content || '').toLowerCase().includes(searchQuery.toLowerCase());
19
+ if (!matchesSearch)
20
+ return false;
21
+ // 2. Category Filter
22
+ if (activeFilter === 'unread')
23
+ return c.unreadCount > 0;
24
+ if (activeFilter === 'favorites')
25
+ return c.isFavorite;
26
+ if (activeFilter === 'groups')
27
+ return c.isGroup;
28
+ return true; // 'all'
29
+ })
30
+ .sort((a, b) => (b.updatedAt || 0) - (a.updatedAt || 0));
31
+ // 3. New Contact Search (Only when searching)
32
+ const additionalContacts = searchQuery.length >= 2
33
+ ? userList.filter((u) => {
34
+ const matchesSearch = u.displayName.toLowerCase().includes(searchQuery.toLowerCase()) ||
35
+ u.username.toLowerCase().includes(searchQuery.toLowerCase());
36
+ const isNotSelf = u.username !== user?.username;
37
+ const notInContacts = !contacts.some(c => c.id === u.username);
38
+ return matchesSearch && isNotSelf && notInContacts;
39
+ }).slice(0, 10)
40
+ : [];
41
+ return (_jsxs("div", { className: "w-full h-full flex flex-col bg-armoyu-bg border-r border-gray-200 dark:border-white/5", children: [_jsxs("div", { className: "p-4 md:p-5 border-b border-gray-200 dark:border-white/5", children: [_jsxs("div", { className: "flex justify-between items-center", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("h2", { className: "text-xl font-bold text-armoyu-text tracking-tight flex items-center gap-2", children: "Sohbetler" }), _jsxs("div", { className: "flex items-center gap-1.5 px-2 py-0.5 rounded-full bg-black/5 dark:bg-white/5 border border-black/5 dark:border-white/5", children: [_jsx("div", { className: `w-1.5 h-1.5 rounded-full ${isConnected ? 'bg-emerald-500 shadow-[0_0_5px_rgba(16,185,129,0.8)]' : 'bg-red-500'} animate-pulse` }), _jsx("span", { className: "text-[10px] font-black text-armoyu-text-muted uppercase tracking-tighter", children: isConnected ? 'Sockete Bağlı' : 'Bağlanıyor...' })] })] }), _jsx("button", { onClick: closeChat, className: "p-2 -mr-2 text-armoyu-text-muted hover:text-red-500 hover:bg-red-500/10 transition-colors rounded-full", title: "Sohbeti Kapat", children: _jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), _jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }) })] }), _jsxs("div", { className: "relative mt-4", children: [_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", className: "absolute left-3 top-1/2 -translate-y-1/2 text-gray-500", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("circle", { cx: "11", cy: "11", r: "8" }), _jsx("line", { x1: "21", y1: "21", x2: "16.65", y2: "16.65" })] }), _jsx("input", { type: "text", placeholder: "Ki\u015Fi ara...", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), className: "w-full bg-white/5 dark:bg-black/20 border border-black/10 dark:border-white/10 rounded-xl pl-10 pr-4 py-2.5 text-sm text-slate-900 dark:text-white placeholder-gray-500 hover:border-black/20 dark:hover:border-white/20 focus:outline-none focus:border-blue-500 transition-all" })] })] }), _jsx(ChatNotes, {}), _jsx("div", { className: "px-4 pb-4 flex gap-2 overflow-x-auto no-scrollbar shrink-0", children: [
42
+ { id: 'all', label: 'Tümü' },
43
+ { id: 'unread', label: 'Okunmamış' },
44
+ { id: 'favorites', label: 'Favoriler' },
45
+ { id: 'groups', label: 'Gruplar' }
46
+ ].map((filter) => (_jsx("button", { onClick: () => setActiveFilter(filter.id), className: `px-4 py-2 rounded-xl text-xs font-black transition-all whitespace-nowrap border ${activeFilter === filter.id
47
+ ? 'bg-blue-500 text-white border-blue-500 shadow-md shadow-blue-500/20 scale-105'
48
+ : 'bg-black/5 dark:bg-white/5 text-armoyu-text-muted border-transparent hover:bg-black/10 dark:hover:bg-white/10'}`, children: filter.label }, filter.id))) }), _jsxs("div", { className: "flex-1 overflow-y-auto no-scrollbar p-3 space-y-1.5", children: [_jsxs("div", { className: "space-y-1.5", children: [searchQuery.length > 0 && filteredActiveContacts.length > 0 && (_jsx("div", { className: "px-3 py-1 text-[10px] font-black text-armoyu-text-muted uppercase tracking-[0.2em] opacity-50", children: "Sohbet Ge\u00E7mi\u015Fi" })), filteredActiveContacts.map(c => (_jsxs("button", { onClick: () => onSelect(c.id), className: `w-full flex items-center gap-4 p-3 rounded-2xl transition-all cursor-pointer text-left ${activeId === c.id
49
+ ? 'bg-blue-500/10 dark:bg-blue-500/20 border border-blue-500/20 shadow-inner'
50
+ : 'hover:bg-black/5 dark:hover:bg-white/5 border border-transparent'}`, children: [_jsxs("div", { className: "relative shrink-0", children: [_jsx("img", { src: c.avatar, alt: c.name, className: "w-12 h-12 rounded-full object-cover border border-white/10 shadow-sm" }), c.isOnline && (_jsx("div", { className: "absolute -bottom-0.5 -right-0.5 w-3.5 h-3.5 bg-green-500 rounded-full border-2 border-white dark:border-[#0a0a0e] shadow-sm" }))] }), _jsxs("div", { className: "flex-1 overflow-hidden", children: [_jsxs("div", { className: "flex justify-between items-center mb-1", children: [_jsx("span", { className: "font-black text-slate-900 dark:text-gray-200 text-sm truncate max-w-[130px]", children: c.name }), _jsx("span", { className: "text-xs text-gray-500 font-black", children: c.time })] }), _jsxs("div", { className: "flex justify-between items-center", children: [_jsx("span", { className: `text-xs truncate max-w-[120px] font-bold ${c.unreadCount > 0 ? 'text-slate-950 dark:text-white' : 'text-slate-500'}`, children: c.lastMessage?.content || 'Mesaj yok' }), c.unreadCount > 0 && (_jsx("span", { className: "bg-blue-500 text-white text-[10px] font-black px-1.5 py-0.5 rounded-md leading-none shadow-md animate-in zoom-in duration-300", children: c.unreadCount > 9 ? '9+' : c.unreadCount }))] })] })] }, c.id)))] }), additionalContacts.length > 0 && (_jsxs("div", { className: "space-y-1.5 mt-6 animate-in fade-in slide-in-from-top-2 duration-500", children: [_jsx("div", { className: "px-3 py-1 text-[10px] font-black text-blue-500 uppercase tracking-[0.2em]", children: "Yeni Sohbet Ba\u015Flat" }), additionalContacts.map((u) => (_jsxs("button", { onClick: () => onSelect(u.username), className: "w-full flex items-center gap-4 p-3 rounded-2xl hover:bg-white/5 border border-transparent transition-all group", children: [_jsx("div", { className: "relative shrink-0", children: _jsx("img", { src: u.avatar, alt: u.displayName, className: "w-12 h-12 rounded-full object-cover border border-white/10 shadow-sm opacity-60 group-hover:opacity-100 transition-opacity" }) }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("div", { className: "font-black text-slate-900 dark:text-gray-200 text-sm truncate", children: u.displayName }), _jsxs("div", { className: "text-[10px] font-bold text-armoyu-text-muted uppercase tracking-tighter", children: ["@", u.username] })] }), _jsx("div", { className: "w-8 h-8 rounded-full bg-blue-500/10 flex items-center justify-center text-blue-500 scale-0 group-hover:scale-100 transition-all duration-300", children: _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: _jsx("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" }) }) })] }, u.username)))] })), searchQuery.length > 0 && filteredActiveContacts.length === 0 && additionalContacts.length === 0 && (_jsx("div", { className: "py-12 text-center", children: _jsx("div", { className: "text-armoyu-text-muted text-sm font-bold opacity-30", children: "Sonu\u00E7 bulunamad\u0131" }) }))] })] }));
51
+ }
52
52
  //# sourceMappingURL=ChatList.js.map