DevouringStars commited on
Commit
e376ddc
·
0 Parent(s):

Initial commit

Browse files
Files changed (3) hide show
  1. chat.html +73 -0
  2. script.js +195 -0
  3. style.css +304 -0
chat.html ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="id">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Chatbot UI</title>
7
+
8
+ <link rel="stylesheet" href="style.css">
9
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css">
10
+ </head>
11
+ <body>
12
+
13
+ <div class="upgrade-tab">
14
+ <i class="fa-solid fa-star"></i> Upgrade to Pro
15
+ </div>
16
+
17
+ <nav class="sidebar">
18
+
19
+ <div class="sidebar-header">
20
+ <a href="#" class="new-chat-btn" role="button">
21
+ <i class="fa-solid fa-plus"></i> New chat
22
+ </a>
23
+ <button class="search-btn">
24
+ <i class="fa-solid fa-search"></i>
25
+ </button>
26
+ </div>
27
+
28
+ <div class="chat-history">
29
+ <div class="history-header">
30
+ <h3>Your conversations</h3>
31
+ <a href="#" class="clear-all">Clear All</a>
32
+ </div>
33
+ <ul id="history-list">
34
+ </ul>
35
+ </div>
36
+
37
+ <div class="sidebar-footer">
38
+ <ul>
39
+ <li><i class="fa-solid fa-cog"></i> Settings</li>
40
+ <li>
41
+ <div class="avatar">AN</div> Andrew Neilson
42
+ </li>
43
+ </ul>
44
+ </div>
45
+ </nav>
46
+
47
+ <section class="chat-area">
48
+
49
+ <header class="chat-header">
50
+ CHAT A.I+
51
+ </header>
52
+
53
+ <div class="chat-log" id="chat-log-area"> <div class="empty-chat-placeholder">
54
+ <i class="fa-solid fa-robot"></i>
55
+ <h2>Hello Name</h2>
56
+ </div>
57
+
58
+ </div>
59
+
60
+ <footer class="chat-input-area">
61
+ <div class="input-wrapper">
62
+ <input type="text" id="chat-input" placeholder="What's in your mind...">
63
+ <button class="send-btn" id="send-button">
64
+ <i class="fa-solid fa-paper-plane"></i>
65
+ </button>
66
+ </div>
67
+ </footer>
68
+
69
+ </section>
70
+
71
+ <script src="script.js"></script>
72
+ </body>
73
+ </html>
script.js ADDED
@@ -0,0 +1,195 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ document.addEventListener("DOMContentLoaded", () => {
2
+ // === 1. MENANGKAP ELEMEN DOM ===
3
+ const sendButton = document.getElementById("send-button");
4
+ const chatInput = document.getElementById("chat-input");
5
+ const historyList = document.getElementById("history-list");
6
+ const chatLog = document.getElementById("chat-log-area");
7
+ const newChatButton = document.querySelector(".new-chat-btn");
8
+
9
+ // Simpan HTML untuk placeholder "chat kosong"
10
+ const emptyChatPlaceholder = `
11
+ <div class="empty-chat-placeholder">
12
+ <i class="fa-solid fa-robot"></i>
13
+ <h2>Hello Name</h2>
14
+ </div>
15
+ `;
16
+
17
+ // === 2. DATA UTAMA APLIKASI (STATE) ===
18
+ let conversations = []; // Menyimpan SEMUA percakapan
19
+ let currentConversationId = null; // Melacak chat mana yang sedang AKTIF
20
+
21
+ // === 3. EVENT LISTENERS ===
22
+
23
+ // Klik tombol "New Chat"
24
+ newChatButton.addEventListener("click", (e) => {
25
+ e.preventDefault(); // Mencegah link <a> me-refresh halaman
26
+ startNewChat();
27
+ });
28
+
29
+ // Klik tombol "Send"
30
+ sendButton.addEventListener("click", sendMessage);
31
+
32
+ // Tekan "Enter" di input
33
+ chatInput.addEventListener("keydown", (event) => {
34
+ if (event.key === "Enter") {
35
+ sendMessage();
36
+ }
37
+ });
38
+
39
+ // Klik salah satu item di history
40
+ historyList.addEventListener("click", (e) => {
41
+ const clickedLi = e.target.closest("li"); // Dapatkan elemen <li> yang diklik
42
+ if (clickedLi) {
43
+ const id = Number(clickedLi.dataset.id); // Ambil ID dari data-attribute
44
+ switchConversation(id);
45
+ }
46
+ });
47
+
48
+ // === 4. FUNGSI-FUNGSI UTAMA ===
49
+
50
+ /**
51
+ * Memulai chat baru (membersihkan area chat)
52
+ */
53
+ function startNewChat() {
54
+ currentConversationId = null; // Set ID chat aktif ke null
55
+ chatInput.value = ""; // Kosongkan input
56
+ renderChatLog(); // Tampilkan placeholder
57
+ renderHistory(); // Perbarui history (untuk hapus highlight 'active')
58
+ }
59
+
60
+ /**
61
+ * Mengirim pesan
62
+ */
63
+ function sendMessage() {
64
+ const messageText = chatInput.value.trim();
65
+ if (messageText === "") return;
66
+
67
+ let activeConversation;
68
+
69
+ if (currentConversationId === null) {
70
+ // Ini adalah chat BARU
71
+ const newId = Date.now(); // Buat ID unik berdasarkan waktu
72
+ activeConversation = {
73
+ id: newId,
74
+ title: messageText.length > 28 ? messageText.substring(0, 28) + "..." : messageText,
75
+ messages: [] // Array pesan untuk chat ini
76
+ };
77
+ conversations.unshift(activeConversation); // Tambahkan ke awal array
78
+ currentConversationId = newId; // Set sebagai chat aktif
79
+ renderHistory(); // Gambar ulang seluruh history list
80
+ } else {
81
+ // Ini adalah chat LAMA
82
+ activeConversation = conversations.find(c => c.id === currentConversationId);
83
+ }
84
+
85
+ // Tambahkan pesan user ke data
86
+ activeConversation.messages.push({ sender: "user", text: messageText });
87
+
88
+ // Tampilkan pesan di layar
89
+ renderChatLog();
90
+ chatInput.value = ""; // Kosongkan input
91
+
92
+ // Simulasikan balasan bot
93
+ simulateBotReply(activeConversation.id, messageText);
94
+ }
95
+
96
+ /**
97
+ * Mengganti percakapan yang aktif
98
+ * @param {number} id - ID percakapan yang ingin dibuka
99
+ */
100
+ function switchConversation(id) {
101
+ if (currentConversationId === id) return; // Jangan lakukan apa-apa jika chat sudah aktif
102
+
103
+ currentConversationId = id;
104
+ renderChatLog();
105
+ renderHistory();
106
+ }
107
+
108
+ /**
109
+ * Menggambar ulang (me-render) seluruh daftar history di sidebar
110
+ */
111
+ function renderHistory() {
112
+ historyList.innerHTML = ""; // Kosongkan list
113
+ conversations.forEach(convo => {
114
+ const li = document.createElement("li");
115
+ li.dataset.id = convo.id; // Simpan ID di data-attribute
116
+ li.innerHTML = `<i class="fa-regular fa-comment-dots"></i> ${convo.title}`;
117
+
118
+ if (convo.id === currentConversationId) {
119
+ li.classList.add("active"); // Beri highlight jika ini chat aktif
120
+ }
121
+ historyList.appendChild(li);
122
+ });
123
+ }
124
+
125
+ /**
126
+ * Menggambar ulang (me-render) seluruh log chat di area kanan
127
+ */
128
+ function renderChatLog() {
129
+ if (currentConversationId === null) {
130
+ // Jika tidak ada chat aktif, tampilkan placeholder
131
+ chatLog.innerHTML = emptyChatPlaceholder;
132
+ return;
133
+ }
134
+
135
+ // Cari data percakapan yang aktif
136
+ const activeConversation = conversations.find(c => c.id === currentConversationId);
137
+ if (!activeConversation) {
138
+ // Jika tidak ketemu (seharusnya tidak terjadi), kembali ke state awal
139
+ startNewChat();
140
+ return;
141
+ }
142
+
143
+ chatLog.innerHTML = ""; // Kosongkan area chat
144
+
145
+ // Loop melalui setiap pesan di percakapan aktif dan buat HTML-nya
146
+ activeConversation.messages.forEach(message => {
147
+ const messageDiv = document.createElement("div");
148
+ messageDiv.classList.add("chat-message", message.sender);
149
+
150
+ let avatar = message.sender === "user" ? "AN" : '<i class="fa-solid fa-robot"></i>';
151
+ let name = message.sender === "user" ? "" : "<strong>CHAT A.I+</strong>";
152
+
153
+ messageDiv.innerHTML = `
154
+ <div class="avatar">${avatar}</div>
155
+ <div class="message-content">
156
+ ${name}
157
+ <p>${message.text}</p>
158
+ </div>
159
+ `;
160
+ chatLog.appendChild(messageDiv);
161
+ });
162
+
163
+ // Auto-scroll ke pesan terbaru
164
+ chatLog.scrollTop = chatLog.scrollHeight;
165
+ }
166
+
167
+ /**
168
+ * Simulasi balasan bot
169
+ * @param {number} convoId - ID chat mana yang harus dibalas
170
+ * @param {string} userMessage - Pesan dari user (untuk logika balasan)
171
+ */
172
+ function simulateBotReply(convoId, userMessage) {
173
+ let botText = "Maaf, saya tidak mengerti."; // Balasan default
174
+
175
+ if (userMessage.toLowerCase().includes("halo")) {
176
+ botText = "Halo juga! Ada yang bisa saya bantu?";
177
+ }
178
+
179
+ setTimeout(() => {
180
+ // Cari percakapan yang benar (bisa jadi user sudah pindah chat)
181
+ const conversationToReply = conversations.find(c => c.id === convoId);
182
+ if (conversationToReply) {
183
+ conversationToReply.messages.push({ sender: "bot", text: botText });
184
+
185
+ // HANYA render ulang jika chat yang dibalas masih aktif
186
+ if (currentConversationId === convoId) {
187
+ renderChatLog();
188
+ }
189
+ }
190
+ }, 1000); // Balas setelah 1 detik
191
+ }
192
+
193
+ // --- Inisialisasi Aplikasi ---
194
+ startNewChat(); // Mulai aplikasi dalam keadaan "New Chat"
195
+ });
style.css ADDED
@@ -0,0 +1,304 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Reset CSS dasar */
2
+ * {
3
+ margin: 0;
4
+ padding: 0;
5
+ box-sizing: border-box;
6
+ }
7
+
8
+ body {
9
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
10
+ background-color: #f7f7f8;
11
+ color: #1f2328;
12
+ display: flex;
13
+ height: 100vh;
14
+ overflow: hidden; /* Mencegah body scroll */
15
+ }
16
+
17
+ /* --- 1. Sidebar (Kiri) --- */
18
+ .sidebar {
19
+ width: 260px;
20
+ background-color: #ffffff;
21
+ border-right: 1px solid #e0e0e0;
22
+ display: flex;
23
+ flex-direction: column;
24
+ padding: 16px;
25
+ }
26
+
27
+ .sidebar-header {
28
+ display: flex;
29
+ align-items: center;
30
+ gap: 10px;
31
+ margin-bottom: 20px;
32
+ }
33
+
34
+ .new-chat-btn {
35
+ flex-grow: 1;
36
+ padding: 12px;
37
+ background-color: #4a4aef; /* Biru seperti di gambar */
38
+ color: white;
39
+ border: none;
40
+ border-radius: 8px;
41
+ font-size: 0.95em;
42
+ font-weight: 500;
43
+ cursor: pointer;
44
+ text-align: left;
45
+ text-decoration: none; /* Ditambahkan agar link tidak ada garis bawah */
46
+ }
47
+
48
+ .new-chat-btn i {
49
+ margin-right: 8px;
50
+ }
51
+
52
+ .search-btn {
53
+ padding: 10px 12px;
54
+ border: 1px solid #ccc;
55
+ background-color: #fff;
56
+ border-radius: 8px;
57
+ cursor: pointer;
58
+ }
59
+
60
+ .chat-history {
61
+ flex-grow: 1; /* Membuat history mengisi ruang tersisa */
62
+ overflow-y: auto; /* Scroll jika history penuh */
63
+ }
64
+
65
+ .history-header {
66
+ display: flex;
67
+ justify-content: space-between;
68
+ align-items: center;
69
+ margin-bottom: 10px;
70
+ padding: 0 8px;
71
+ }
72
+
73
+ .history-header h3 {
74
+ font-size: 0.8em;
75
+ color: #6c757d;
76
+ font-weight: 600;
77
+ }
78
+
79
+ .history-header .clear-all {
80
+ font-size: 0.8em;
81
+ color: #6c757d;
82
+ text-decoration: none;
83
+ }
84
+
85
+ .chat-history ul {
86
+ list-style: none;
87
+ }
88
+
89
+ .chat-history li {
90
+ display: flex;
91
+ align-items: center;
92
+ gap: 10px;
93
+ padding: 10px 8px;
94
+ border-radius: 6px;
95
+ cursor: pointer;
96
+ font-size: 0.9em;
97
+ white-space: nowrap;
98
+ overflow: hidden;
99
+ text-overflow: ellipsis;
100
+ }
101
+
102
+ .chat-history li:hover,
103
+ .chat-history li.active {
104
+ background-color: #f0f0f0;
105
+ }
106
+
107
+ .chat-history li i {
108
+ color: #6c757d;
109
+ }
110
+
111
+ .sidebar-footer {
112
+ border-top: 1px solid #e0e0e0;
113
+ padding-top: 16px;
114
+ }
115
+
116
+ .sidebar-footer ul {
117
+ list-style: none;
118
+ }
119
+
120
+ .sidebar-footer li {
121
+ display: flex;
122
+ align-items: center;
123
+ gap: 10px;
124
+ padding: 10px 8px;
125
+ border-radius: 6px;
126
+ cursor: pointer;
127
+ font-size: 0.9em;
128
+ }
129
+
130
+ .sidebar-footer li:hover {
131
+ background-color: #f0f0f0;
132
+ }
133
+
134
+ .sidebar-footer .avatar {
135
+ width: 24px;
136
+ height: 24px;
137
+ border-radius: 50%;
138
+ background-color: #ddd;
139
+ }
140
+
141
+ /* --- 2. Chat Area (Kanan) --- */
142
+ .chat-area {
143
+ flex-grow: 1; /* Mengisi sisa ruang */
144
+ display: flex;
145
+ flex-direction: column;
146
+ background-color: #ffffff;
147
+ height: 100vh;
148
+ }
149
+
150
+ .chat-header {
151
+ padding: 20px;
152
+ border-bottom: 1px solid #e0e0e0;
153
+ font-size: 1.1em;
154
+ font-weight: 600;
155
+ flex-shrink: 0; /* Mencegah header mengecil */
156
+ }
157
+
158
+ .chat-log {
159
+ flex-grow: 1; /* Mengisi ruang tengah */
160
+ overflow-y: auto; /* Ini adalah area chat yang bisa di-scroll */
161
+ padding: 24px;
162
+ display: flex;
163
+ flex-direction: column;
164
+ gap: 20px; /* Jarak antar pesan NANTINYA */
165
+ }
166
+
167
+ /* --- STYLE UNTUK EMPTY STATE --- */
168
+ .empty-chat-placeholder {
169
+ flex-grow: 1; /* Memastikan placeholder mengisi ruang chat-log */
170
+ display: flex;
171
+ flex-direction: column;
172
+ align-items: center;
173
+ justify-content: center;
174
+ text-align: center;
175
+ color: #aaa;
176
+ }
177
+
178
+ .empty-chat-placeholder i {
179
+ font-size: 4em;
180
+ margin-bottom: 20px;
181
+ opacity: 0.5;
182
+ }
183
+
184
+ .empty-chat-placeholder h2 {
185
+ font-size: 1.5em;
186
+ font-weight: 500;
187
+ }
188
+ /* ------------------------------- */
189
+
190
+
191
+ /* Styling untuk setiap pesan (Disimpan untuk nanti saat Anda tambahkan chat) */
192
+ .chat-message {
193
+ display: flex;
194
+ gap: 16px;
195
+ max-width: 90%; /* Agar tidak terlalu lebar */
196
+ }
197
+
198
+ .chat-message .avatar {
199
+ width: 40px;
200
+ height: 40px;
201
+ border-radius: 50%;
202
+ background-color: #f0f0f0;
203
+ display: flex;
204
+ align-items: center;
205
+ justify-content: center;
206
+ font-weight: bold;
207
+ flex-shrink: 0;
208
+ }
209
+
210
+ .chat-message.user .avatar {
211
+ background-color: #cce5ff;
212
+ }
213
+
214
+ .chat-message.bot .avatar {
215
+ background-color: #d1e7dd;
216
+ }
217
+
218
+ .message-content {
219
+ padding-top: 8px;
220
+ }
221
+
222
+ .message-content strong { /* Untuk nama "CHAT A.I+" */
223
+ display: block;
224
+ margin-bottom: 4px;
225
+ font-size: 1.05em;
226
+ }
227
+
228
+ .message-content p,
229
+ .message-content ol {
230
+ line-height: 1.6;
231
+ }
232
+
233
+ .message-content ol {
234
+ padding-left: 20px; /* Indentasi untuk ordered list */
235
+ margin-top: 10px;
236
+ }
237
+
238
+ .message-content li {
239
+ margin-bottom: 8px;
240
+ }
241
+
242
+ /* Area Input di Bawah */
243
+ .chat-input-area {
244
+ padding: 24px;
245
+ border-top: 1px solid #e0e0e0;
246
+ background-color: #fff;
247
+ flex-shrink: 0; /* Mencegah input area mengecil */
248
+ }
249
+
250
+ .input-wrapper {
251
+ display: flex;
252
+ position: relative;
253
+ max-width: 900px; /* Batasi lebar input */
254
+ margin: 0 auto; /* tengahkan */
255
+ }
256
+
257
+ .chat-input-area input {
258
+ flex-grow: 1;
259
+ padding: 16px 50px 16px 20px; /* Beri ruang untuk tombol send */
260
+ border: 1px solid #ccc;
261
+ border-radius: 8px;
262
+ font-size: 1em;
263
+ }
264
+
265
+ .chat-input-area input:focus {
266
+ outline: none;
267
+ border-color: #4a4aef;
268
+ box-shadow: 0 0 0 2px #4a4aef30;
269
+ }
270
+
271
+ .send-btn {
272
+ position: absolute;
273
+ right: 10px;
274
+ top: 50%;
275
+ transform: translateY(-50%);
276
+ background-color: #4a4aef;
277
+ color: white;
278
+ border: none;
279
+ width: 40px;
280
+ height: 40px;
281
+ border-radius: 50%; /* Buat jadi lingkaran */
282
+ font-size: 1.1em;
283
+ cursor: pointer;
284
+ display: flex;
285
+ align-items: center;
286
+ justify-content: center;
287
+ }
288
+
289
+ /* Tab "Upgrade" di sisi kanan */
290
+ .upgrade-tab {
291
+ position: fixed;
292
+ top: 50%;
293
+ right: -60px; /* Atur posisi agar sedikit keluar */
294
+ transform: translateY(-50%) rotate(-90deg);
295
+ background-color: #4a4aef;
296
+ color: white;
297
+ padding: 10px 20px;
298
+ font-size: 0.9em;
299
+ font-weight: bold;
300
+ border-top-left-radius: 8px;
301
+ border-top-right-radius: 8px;
302
+ cursor: pointer;
303
+ z-index: 10;
304
+ }