ALDI WAHYUDIN commited on
Commit
dd20ee6
·
verified ·
1 Parent(s): fb1f1a5

bagian chat list di kiri bisa di sembnyikan dan di rampilkan dengan tombol icon berger di kiri atas - Initial Deployment

Browse files
Files changed (3) hide show
  1. README.md +7 -5
  2. index.html +438 -18
  3. prompts.txt +0 -0
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Test
3
- emoji: 🐨
4
- colorFrom: blue
5
- colorTo: indigo
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: test
3
+ emoji: 🐳
4
+ colorFrom: green
5
+ colorTo: green
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,439 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  </html>
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>WhatsApp Web Clone</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link href="https://unpkg.com/aos@2.3.1/dist/aos.css" rel="stylesheet">
9
+ <script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
10
+ <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
11
+ <script src="https://unpkg.com/feather-icons"></script>
12
+ <style>
13
+ .chat-container {
14
+ height: calc(100vh - 120px);
15
+ }
16
+ .message-input {
17
+ resize: none;
18
+ }
19
+ .scrollbar-hide::-webkit-scrollbar {
20
+ display: none;
21
+ }
22
+ .scrollbar-hide {
23
+ -ms-overflow-style: none;
24
+ scrollbar-width: none;
25
+ }
26
+ .typing-indicator::after {
27
+ content: '...';
28
+ animation: typing 1.5s infinite;
29
+ display: inline-block;
30
+ width: 0;
31
+ }
32
+ @keyframes typing {
33
+ 0% { width: 0; }
34
+ 50% { width: 0.5em; }
35
+ 100% { width: 1em; }
36
+ }
37
+ </style>
38
+ </head>
39
+ <body class="bg-gray-100">
40
+ <div class="flex flex-col h-screen">
41
+ <!-- Header -->
42
+ <div class="bg-gradient-to-r from-indigo-600 to-purple-600 text-white p-4 shadow-md">
43
+ <div class="flex items-center justify-between">
44
+ <div class="flex items-center space-x-4">
45
+ <button id="toggle-sidebar" class="p-1 rounded-full hover:bg-indigo-700">
46
+ <i data-feather="menu" class="w-6 h-6"></i>
47
+ </button>
48
+ <i data-feather="message-circle" class="w-6 h-6"></i>
49
+ <h1 class="text-xl font-semibold">WhatsApp Web</h1>
50
+ </div>
51
+ <div class="flex items-center space-x-4">
52
+ <button id="refresh-btn" class="p-2 rounded-full hover:bg-emerald-600">
53
+ <i data-feather="refresh-cw" class="w-5 h-5"></i>
54
+ </button>
55
+ <button id="settings-btn" class="p-2 rounded-full hover:bg-emerald-600">
56
+ <i data-feather="settings" class="w-5 h-5"></i>
57
+ </button>
58
+ </div>
59
+ </div>
60
+ </div>
61
+
62
+ <!-- Main Content -->
63
+ <div class="flex flex-1 overflow-hidden">
64
+ <!-- Sidebar -->
65
+ <div id="sidebar" class="w-1/3 border-r border-gray-300 bg-white flex flex-col transition-all duration-300 ease-in-out">
66
+ <!-- Search -->
67
+ <div class="p-3 bg-gray-50">
68
+ <div class="relative">
69
+ <input type="text" placeholder="Search or start new chat"
70
+ class="w-full py-2 pl-10 pr-4 bg-white rounded-lg focus:outline-none focus:ring-2 focus:ring-emerald-500">
71
+ <i data-feather="search" class="absolute left-3 top-2.5 text-gray-400"></i>
72
+ </div>
73
+ </div>
74
+
75
+ <!-- Chat List -->
76
+ <div class="flex-1 overflow-y-auto scrollbar-hide">
77
+ <div id="chat-list" class="divide-y divide-gray-200">
78
+ <!-- Chat items will be added here dynamically -->
79
+ </div>
80
+ </div>
81
+ </div>
82
+
83
+ <!-- Chat Area -->
84
+ <div class="flex-1 flex flex-col bg-gray-100">
85
+ <!-- Chat Header -->
86
+ <div id="chat-header" class="p-3 bg-white border-b border-gray-300 flex items-center justify-between">
87
+ <div class="flex items-center space-x-3">
88
+ <div class="w-10 h-10 rounded-full bg-gray-300 flex items-center justify-center">
89
+ <i data-feather="user" class="text-gray-500"></i>
90
+ </div>
91
+ <div>
92
+ <h3 class="font-semibold">Select a chat</h3>
93
+ <p class="text-xs text-gray-500">Last seen</p>
94
+ </div>
95
+ </div>
96
+ <div class="flex items-center space-x-4">
97
+ <button class="p-2 rounded-full hover:bg-gray-200">
98
+ <i data-feather="search" class="w-5 h-5"></i>
99
+ </button>
100
+ <button class="p-2 rounded-full hover:bg-gray-200">
101
+ <i data-feather="more-vertical" class="w-5 h-5"></i>
102
+ </button>
103
+ </div>
104
+ </div>
105
+
106
+ <!-- Messages -->
107
+ <div id="messages-container" class="flex-1 overflow-y-auto p-4 space-y-3 scrollbar-hide">
108
+ <div class="text-center py-10 text-gray-500">
109
+ <i data-feather="message-circle" class="w-12 h-12 mx-auto mb-2"></i>
110
+ <p>Select a chat to start messaging</p>
111
+ </div>
112
+ </div>
113
+
114
+ <!-- Message Input -->
115
+ <div id="message-input-container" class="p-3 bg-white border-t border-gray-300 hidden">
116
+ <div class="flex items-center space-x-2">
117
+ <button class="p-2 rounded-full hover:bg-gray-200">
118
+ <i data-feather="smile" class="w-5 h-5"></i>
119
+ </button>
120
+ <button class="p-2 rounded-full hover:bg-gray-200">
121
+ <i data-feather="paperclip" class="w-5 h-5"></i>
122
+ </button>
123
+ <div class="flex-1">
124
+ <textarea id="message-input" rows="1" placeholder="Type a message"
125
+ class="w-full py-2 px-4 bg-gray-100 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500 message-input"></textarea>
126
+ </div>
127
+ <button id="send-btn" class="p-2 rounded-full bg-gradient-to-r from-indigo-500 to-purple-500 text-white hover:from-indigo-600 hover:to-purple-600 shadow-lg">
128
+ <i data-feather="send" class="w-5 h-5"></i>
129
+ </button>
130
+ </div>
131
+ </div>
132
+ </div>
133
+ </div>
134
+ </div>
135
+
136
+ <!-- Settings Modal -->
137
+ <div id="settings-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center hidden">
138
+ <div class="bg-white rounded-lg w-full max-w-md">
139
+ <div class="p-4 border-b border-gray-200 flex justify-between items-center">
140
+ <h3 class="text-lg font-semibold">Settings</h3>
141
+ <button id="close-settings" class="p-1 rounded-full hover:bg-gray-200">
142
+ <i data-feather="x" class="w-5 h-5"></i>
143
+ </button>
144
+ </div>
145
+ <div class="p-4 space-y-4">
146
+ <div class="flex items-center space-x-4">
147
+ <div class="w-12 h-12 rounded-full bg-gray-300 flex items-center justify-center">
148
+ <i data-feather="user" class="text-gray-500"></i>
149
+ </div>
150
+ <div>
151
+ <h4 class="font-medium">User Profile</h4>
152
+ <p class="text-sm text-gray-500">Update your profile information</p>
153
+ </div>
154
+ </div>
155
+ <div class="space-y-2">
156
+ <div class="flex items-center justify-between p-3 hover:bg-gray-100 rounded-lg cursor-pointer">
157
+ <div class="flex items-center space-x-3">
158
+ <i data-feather="user" class="w-5 h-5 text-gray-500"></i>
159
+ <span>Profile</span>
160
+ </div>
161
+ <i data-feather="chevron-right" class="w-5 h-5 text-gray-400"></i>
162
+ </div>
163
+ <div class="flex items-center justify-between p-3 hover:bg-gray-100 rounded-lg cursor-pointer">
164
+ <div class="flex items-center space-x-3">
165
+ <i data-feather="lock" class="w-5 h-5 text-purple-500"></i>
166
+ <span class="text-purple-600">Privacy</span>
167
+ </div>
168
+ <i data-feather="chevron-right" class="w-5 h-5 text-purple-400"></i>
169
+ </div>
170
+ <div class="flex items-center justify-between p-3 hover:bg-gray-100 rounded-lg cursor-pointer">
171
+ <div class="flex items-center space-x-3">
172
+ <i data-feather="bell" class="w-5 h-5 text-indigo-500"></i>
173
+ <span class="text-indigo-600">Notifications</span>
174
+ </div>
175
+ <i data-feather="chevron-right" class="w-5 h-5 text-indigo-400"></i>
176
+ </div>
177
+ </div>
178
+ </div>
179
+ <div class="p-4 border-t border-gray-200">
180
+ <button id="logout-btn" class="w-full py-2 px-4 bg-red-600 text-white rounded-lg hover:bg-red-700">
181
+ Logout
182
+ </button>
183
+ </div>
184
+ </div>
185
+ </div>
186
+
187
+ <script>
188
+ // Initialize AOS and Feather Icons
189
+ AOS.init();
190
+ feather.replace();
191
+
192
+ // Sample data for demonstration
193
+ let chats = [];
194
+ let currentChat = null;
195
+
196
+ let messages = {};
197
+
198
+ // DOM Elements
199
+ const chatList = document.getElementById('chat-list');
200
+ const sidebar = document.getElementById('sidebar');
201
+ const toggleSidebarBtn = document.getElementById('toggle-sidebar');
202
+ const messagesContainer = document.getElementById('messages-container');
203
+ const messageInputContainer = document.getElementById('message-input-container');
204
+ const messageInput = document.getElementById('message-input');
205
+ const sendBtn = document.getElementById('send-btn');
206
+ const chatHeader = document.getElementById('chat-header');
207
+ const settingsBtn = document.getElementById('settings-btn');
208
+ const settingsModal = document.getElementById('settings-modal');
209
+ const closeSettings = document.getElementById('close-settings');
210
+ const refreshBtn = document.getElementById('refresh-btn');
211
+ const logoutBtn = document.getElementById('logout-btn');
212
+
213
+ // API base URL
214
+ const API_BASE = 'http://localhost:3000';
215
+
216
+ // Fetch chats from API
217
+ async function fetchChats() {
218
+ try {
219
+ const response = await fetch(`${API_BASE}/chats`);
220
+ const data = await response.json();
221
+ if (data.code === 'SUCCESS') {
222
+ chats = data.results.data;
223
+ renderChatList();
224
+ }
225
+ } catch (error) {
226
+ console.error('Error fetching chats:', error);
227
+ }
228
+ }
229
+
230
+ // Render chat list
231
+ function renderChatList() {
232
+ chatList.innerHTML = '';
233
+ chats.forEach(chat => {
234
+ const chatItem = document.createElement('div');
235
+ chatItem.className = `p-3 flex items-center space-x-3 hover:bg-gray-100 cursor-pointer ${chat.unread > 0 ? 'bg-gray-50' : ''}`;
236
+ chatItem.dataset.chatId = chat.id;
237
+ chatItem.innerHTML = `
238
+ <div class="relative">
239
+ <div class="w-12 h-12 rounded-full bg-gray-300 flex items-center justify-center">
240
+ <i data-feather="user" class="text-gray-500"></i>
241
+ </div>
242
+ ${chat.isOnline ? `<div class="absolute bottom-0 right-0 w-3 h-3 bg-green-500 rounded-full border-2 border-white"></div>` : ''}
243
+ </div>
244
+ <div class="flex-1 min-w-0">
245
+ <div class="flex justify-between items-center">
246
+ <h4 class="font-medium truncate">${chat.name}</h4>
247
+ <span class="text-xs text-gray-500 whitespace-nowrap">${chat.time}</span>
248
+ </div>
249
+ <div class="flex justify-between items-center">
250
+ <p class="text-sm text-gray-500 truncate">${chat.lastMessage}</p>
251
+ ${chat.unread > 0 ? `<span class="bg-purple-600 text-white text-xs rounded-full h-5 w-5 flex items-center justify-center">${chat.unread}</span>` : ''}
252
+ </div>
253
+ </div>
254
+ `;
255
+ chatItem.addEventListener('click', () => loadChat(chat.id));
256
+ chatList.appendChild(chatItem);
257
+ });
258
+ feather.replace();
259
+ }
260
+
261
+ // Load chat messages
262
+ async function loadChat(chatJid) {
263
+ currentChat = chatJid;
264
+
265
+ try {
266
+ // Fetch chat info
267
+ const infoResponse = await fetch(`${API_BASE}/user/info?phone=${encodeURIComponent(chatJid)}`);
268
+ const infoData = await infoResponse.json();
269
+
270
+ // Fetch messages
271
+ const messagesResponse = await fetch(`${API_BASE}/chat/${encodeURIComponent(chatJid)}/messages`);
272
+ const messagesData = await messagesResponse.json();
273
+
274
+ if (infoData.code === 'SUCCESS' && messagesData.code === 'SUCCESS') {
275
+ const chatInfo = infoData.results;
276
+ messages[chatJid] = messagesData.results.data;
277
+
278
+ // Update chat header
279
+ chatHeader.innerHTML = `
280
+ <div class="flex items-center space-x-3">
281
+ <div class="relative">
282
+ <div class="w-10 h-10 rounded-full bg-gray-300 flex items-center justify-center">
283
+ <i data-feather="user" class="text-gray-500"></i>
284
+ </div>
285
+ ${chatInfo.isOnline ? `<div class="absolute bottom-0 right-0 w-2 h-2 bg-green-500 rounded-full border border-white"></div>` : ''}
286
+ </div>
287
+ <div>
288
+ <h3 class="font-semibold">${chatInfo.verified_name || chatJid}</h3>
289
+ <p class="text-xs text-gray-500">${chatInfo.isOnline ? 'online' : 'last seen recently'}</p>
290
+ </div>
291
+ </div>
292
+ <div class="flex items-center space-x-4">
293
+ <button class="p-2 rounded-full hover:bg-gray-200">
294
+ <i data-feather="search" class="w-5 h-5"></i>
295
+ </button>
296
+ <button class="p-2 rounded-full hover:bg-gray-200">
297
+ <i data-feather="more-vertical" class="w-5 h-5"></i>
298
+ </button>
299
+ </div>
300
+ `;
301
+
302
+ // Render messages
303
+ messagesContainer.innerHTML = '';
304
+ messages.forEach(msg => {
305
+ const messageDiv = document.createElement('div');
306
+ messageDiv.className = `flex ${msg.isMe ? 'justify-end' : 'justify-start'}`;
307
+ messageDiv.innerHTML = `
308
+ <div class="max-w-xs md:max-w-md lg:max-w-lg rounded-lg p-3 ${msg.isMe ? 'bg-gradient-to-r from-indigo-100 to-purple-100' : 'bg-white'} shadow">
309
+ <p>${msg.text}</p>
310
+ <p class="text-xs text-gray-500 text-right mt-1">${msg.time}</p>
311
+ </div>
312
+ `;
313
+ messagesContainer.appendChild(messageDiv);
314
+ });
315
+
316
+ // Scroll to bottom
317
+ messagesContainer.scrollTop = messagesContainer.scrollHeight;
318
+
319
+ // Show message input
320
+ messageInputContainer.classList.remove('hidden');
321
+ messageInput.focus();
322
+
323
+ feather.replace();
324
+ }
325
+
326
+ // Send message
327
+ async function sendMessage() {
328
+ const text = messageInput.value.trim();
329
+ if (!text || !currentChat) return;
330
+
331
+ try {
332
+ // Show typing indicator
333
+ await fetch(`${API_BASE}/send/chat-presence`, {
334
+ method: 'POST',
335
+ headers: {
336
+ 'Content-Type': 'application/json'
337
+ },
338
+ body: JSON.stringify({
339
+ phone: currentChat,
340
+ action: 'start'
341
+ })
342
+ });
343
+
344
+ // Send message
345
+ const response = await fetch(`${API_BASE}/send/message`, {
346
+ method: 'POST',
347
+ headers: {
348
+ 'Content-Type': 'application/json'
349
+ },
350
+ body: JSON.stringify({
351
+ phone: currentChat,
352
+ message: text
353
+ })
354
+ });
355
+
356
+ const data = await response.json();
357
+
358
+ if (data.code === 'SUCCESS') {
359
+ // Add message to UI
360
+ const messageDiv = document.createElement('div');
361
+ messageDiv.className = 'flex justify-end';
362
+ messageDiv.innerHTML = `
363
+ <div class="max-w-xs md:max-w-md lg:max-w-lg rounded-lg p-3 bg-gradient-to-r from-emerald-100 to-teal-100 shadow">
364
+ <p>${text}</p>
365
+ <p class="text-xs text-gray-500 text-right mt-1">Just now</p>
366
+ </div>
367
+ `;
368
+ messagesContainer.appendChild(messageDiv);
369
+ messageInput.value = '';
370
+ messagesContainer.scrollTop = messagesContainer.scrollHeight;
371
+
372
+ // Stop typing indicator
373
+ await fetch(`${API_BASE}/send/chat-presence`, {
374
+ method: 'POST',
375
+ headers: {
376
+ 'Content-Type': 'application/json'
377
+ },
378
+ body: JSON.stringify({
379
+ phone: currentChat,
380
+ action: 'stop'
381
+ })
382
+ });
383
+
384
+ // Refresh messages
385
+ loadChat(currentChat);
386
+ }
387
+ } catch (error) {
388
+ console.error('Error sending message:', error);
389
+ }
390
+ }
391
+
392
+ // Event Listeners
393
+ sendBtn.addEventListener('click', sendMessage);
394
+ messageInput.addEventListener('keypress', (e) => {
395
+ if (e.key === 'Enter' && !e.shiftKey) {
396
+ e.preventDefault();
397
+ sendMessage();
398
+ }
399
+ });
400
+
401
+ settingsBtn.addEventListener('click', () => {
402
+ settingsModal.classList.remove('hidden');
403
+ });
404
+
405
+ closeSettings.addEventListener('click', () => {
406
+ settingsModal.classList.add('hidden');
407
+ });
408
+
409
+ refreshBtn.addEventListener('click', () => {
410
+ fetchChats();
411
+ if (currentChat) {
412
+ loadChat(currentChat);
413
+ }
414
+ });
415
+
416
+ logoutBtn.addEventListener('click', async () => {
417
+ try {
418
+ const response = await fetch(`${API_BASE}/app/logout`);
419
+ const data = await response.json();
420
+ if (data.code === 'SUCCESS') {
421
+ window.location.reload();
422
+ }
423
+ } catch (error) {
424
+ console.error('Error logging out:', error);
425
+ }
426
+ settingsModal.classList.add('hidden');
427
+ });
428
+
429
+ // Toggle sidebar
430
+ toggleSidebarBtn.addEventListener('click', () => {
431
+ sidebar.classList.toggle('hidden');
432
+ feather.replace();
433
+ });
434
+
435
+ // Initialize
436
+ fetchChats();
437
+ </script>
438
+ </body>
439
  </html>
prompts.txt ADDED
The diff for this file is too large to render. See raw diff