andrewwda commited on
Commit
bbb90b5
Β·
verified Β·
1 Parent(s): c09349d

Update templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +243 -99
templates/index.html CHANGED
@@ -16,29 +16,27 @@
16
  font-family: 'Segoe UI', 'Poppins', 'Inter', system-ui, -apple-system, sans-serif;
17
  }
18
 
19
- /* FIX 2: Set html dan body ke 100% mutlak dengan background supaya tidak ada background putih yang bocor */
20
  html, body {
21
- height: 100%;
22
  width: 100%;
 
23
  background-color: #0a0c15;
24
  overflow: hidden;
25
  }
26
 
27
- body {
28
- height: 100dvh; /* Tetap pertahankan dvh untuk browser modern */
29
- -webkit-tap-highlight-color: transparent;
30
- touch-action: pan-x pan-y;
31
- }
32
-
33
- /* =========================
34
- APP
35
- ========================= */
36
  .app {
 
 
 
 
 
37
  display: flex;
38
  flex-direction: column;
39
- height: 100%;
40
  width: 100%;
41
- position: relative;
 
 
42
  }
43
 
44
  /* =========================
@@ -55,6 +53,7 @@
55
  position: fixed;
56
  left: -320px;
57
  top: 0;
 
58
  height: 100%;
59
  z-index: 999;
60
  transition: 0.3s cubic-bezier(0.4, 0, 0.2, 1);
@@ -122,11 +121,6 @@
122
  box-shadow: 0 4px 12px rgba(0, 212, 255, 0.3);
123
  }
124
 
125
- .new-chat:hover {
126
- transform: translateY(-2px);
127
- box-shadow: 0 6px 20px rgba(0, 212, 255, 0.5);
128
- }
129
-
130
  .chat-history {
131
  flex: 1;
132
  overflow-y: auto;
@@ -171,28 +165,27 @@
171
  }
172
 
173
  /* =========================
174
- MAIN - CYBER DARK
175
  ========================= */
176
  .main {
177
  display: flex;
178
  flex-direction: column;
179
  width: 100%;
180
- height: 100%; /* FIX 3: Pastikan .main selalu 100% mengikuti parent */
181
  overflow: hidden;
182
- background: #0a0c15;
183
  }
184
 
185
  /* =========================
186
- TOPBAR - NEO MASCULINE
187
  ========================= */
188
  .topbar {
189
- flex-shrink: 0; /* FIX 4: Kunci flex supaya topbar tidak ikutan tertekan/mengecil */
190
- height: 80px;
191
  background: rgba(10, 12, 21, 0.95);
192
  backdrop-filter: blur(10px);
193
  display: flex;
194
  align-items: center;
195
- padding: 0 30px;
196
  color: #e8edff;
197
  border-bottom: 1px solid rgba(0, 212, 255, 0.3);
198
  box-shadow: 0 2px 20px rgba(0, 0, 0, 0.3);
@@ -200,24 +193,22 @@
200
  }
201
 
202
  .menu-btn {
203
- font-size: 28px;
204
- margin-right: 20px;
205
  cursor: pointer;
206
- transition: 0.2s;
207
  color: #00d4ff;
208
  }
209
 
210
  .logo {
211
  flex-shrink: 0;
212
- width: 50px;
213
- height: 50px;
214
- border-radius: 14px;
215
  background: linear-gradient(135deg, #00d4ff, #0099ff);
216
  display: flex;
217
  align-items: center;
218
  justify-content: center;
219
- margin-right: 15px;
220
- box-shadow: 0 0 12px rgba(0, 212, 255, 0.5);
221
  overflow: hidden;
222
  }
223
 
@@ -225,12 +216,10 @@
225
  width: 100%;
226
  height: 100%;
227
  object-fit: cover;
228
- border-radius: 14px;
229
  }
230
 
231
  .title h1 {
232
- font-size: 24px;
233
- letter-spacing: -0.5px;
234
  background: linear-gradient(135deg, #e8edff, #00d4ff);
235
  -webkit-background-clip: text;
236
  background-clip: text;
@@ -238,72 +227,48 @@
238
  }
239
 
240
  .title p {
241
- font-size: 13px;
242
  color: #00d4ff;
243
  display: flex;
244
  align-items: center;
245
- gap: 6px;
246
  }
247
 
248
  .title p::before {
249
  content: "●";
250
- font-size: 10px;
251
  color: #00ff88;
252
- text-shadow: 0 0 5px #00ff88;
253
  }
254
 
255
  /* =========================
256
- CHAT AREA - GLASS
257
  ========================= */
258
  .chat-area {
259
- flex: 1 1 0%; /* FIX 5: Aturan flex terbaik untuk scroll-area mobile */
260
  overflow-y: auto;
261
- padding: 15px;
262
  background: linear-gradient(180deg, #0a0c15 0%, #0f111a 100%);
263
  -webkit-overflow-scrolling: touch;
264
- }
265
-
266
- .chat-area::-webkit-scrollbar {
267
- width: 6px;
268
- }
269
- .chat-area::-webkit-scrollbar-track {
270
- background: #1a1f2e;
271
- border-radius: 10px;
272
- }
273
- .chat-area::-webkit-scrollbar-thumb {
274
- background: #00d4ff;
275
- border-radius: 10px;
276
  }
277
 
278
  .message {
279
  max-width: 85%;
280
- padding: 14px 20px;
281
- border-radius: 20px;
282
- margin-bottom: 20px;
283
- font-size: 16px;
284
- line-height: 1.5;
285
  word-wrap: break-word;
286
- animation: fadeInUp 0.3s ease;
287
- }
288
-
289
- @keyframes fadeInUp {
290
- from {
291
- opacity: 0;
292
- transform: translateY(10px);
293
- }
294
- to {
295
- opacity: 1;
296
- transform: translateY(0);
297
- }
298
  }
299
 
300
  .bot {
301
  background: rgba(20, 24, 40, 0.9);
302
- backdrop-filter: blur(10px);
303
  border: 1px solid rgba(0, 212, 255, 0.2);
304
  color: #d0d9ff;
305
- border-bottom-left-radius: 6px;
306
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
307
  align-self: flex-start;
308
  }
309
 
@@ -311,43 +276,37 @@
311
  background: linear-gradient(135deg, #00d4ff, #0099ff);
312
  color: #0a0c15;
313
  font-weight: 600;
 
 
314
  margin-left: auto;
315
- border-bottom-right-radius: 6px;
316
- box-shadow: 0 4px 15px rgba(0, 212, 255, 0.3);
317
  }
318
 
319
  /* =========================
320
- INPUT - CYBER
321
  ========================= */
322
  .input-area {
323
- flex-shrink: 0; /* FIX 6: Kunci flex supaya input area selalu di bawah & dimensinya tetap */
324
  display: flex;
325
- padding: 20px 30px;
326
- gap: 15px;
327
- background: rgba(10, 12, 21, 0.95);
328
- backdrop-filter: blur(10px);
329
- border-top: 1px solid rgba(0, 212, 255, 0.2);
330
  }
331
 
332
  input {
333
  flex: 1;
334
- border: 1px solid rgba(0, 212, 255, 0.3);
335
  background: rgba(18, 22, 40, 0.8);
336
- border-radius: 18px;
337
- padding: 16px 22px;
338
- font-size: 16px; /* Mencegah auto-zoom di iOS */
339
  outline: none;
340
  color: #e8edff;
341
- transition: all 0.2s;
342
  }
343
 
344
  input:focus {
345
  border-color: #00d4ff;
346
- box-shadow: 0 0 12px rgba(0, 212, 255, 0.3);
347
- }
348
-
349
- input::placeholder {
350
- color: #4a5578;
351
  }
352
 
353
  button.send {
@@ -356,11 +315,196 @@
356
  background: linear-gradient(135deg, #00d4ff, #0099ff);
357
  color: #0a0c15;
358
  font-weight: bold;
359
- padding: 0 32px;
360
- border-radius: 18px;
361
- font-size: 16px;
362
  cursor: pointer;
363
- transition: 0.2s;
364
  display: flex;
365
  align-items: center;
366
- gap: 8px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  font-family: 'Segoe UI', 'Poppins', 'Inter', system-ui, -apple-system, sans-serif;
17
  }
18
 
19
+ /* PERBAIKAN TOTAL: Amankan background dasar */
20
  html, body {
 
21
  width: 100%;
22
+ height: 100%;
23
  background-color: #0a0c15;
24
  overflow: hidden;
25
  }
26
 
27
+ /* ANTI-BLANK TRICK: Kunci aplikasi langsung ke ukuran viewport jendela HP */
 
 
 
 
 
 
 
 
28
  .app {
29
+ position: fixed;
30
+ top: 0;
31
+ left: 0;
32
+ right: 0;
33
+ bottom: 0;
34
  display: flex;
35
  flex-direction: column;
 
36
  width: 100%;
37
+ height: 100%;
38
+ overflow: hidden;
39
+ background-color: #0a0c15;
40
  }
41
 
42
  /* =========================
 
53
  position: fixed;
54
  left: -320px;
55
  top: 0;
56
+ bottom: 0;
57
  height: 100%;
58
  z-index: 999;
59
  transition: 0.3s cubic-bezier(0.4, 0, 0.2, 1);
 
121
  box-shadow: 0 4px 12px rgba(0, 212, 255, 0.3);
122
  }
123
 
 
 
 
 
 
124
  .chat-history {
125
  flex: 1;
126
  overflow-y: auto;
 
165
  }
166
 
167
  /* =========================
168
+ MAIN AREA
169
  ========================= */
170
  .main {
171
  display: flex;
172
  flex-direction: column;
173
  width: 100%;
174
+ height: 100%;
175
  overflow: hidden;
 
176
  }
177
 
178
  /* =========================
179
+ TOPBAR
180
  ========================= */
181
  .topbar {
182
+ flex-shrink: 0;
183
+ height: 70px;
184
  background: rgba(10, 12, 21, 0.95);
185
  backdrop-filter: blur(10px);
186
  display: flex;
187
  align-items: center;
188
+ padding: 0 20px;
189
  color: #e8edff;
190
  border-bottom: 1px solid rgba(0, 212, 255, 0.3);
191
  box-shadow: 0 2px 20px rgba(0, 0, 0, 0.3);
 
193
  }
194
 
195
  .menu-btn {
196
+ font-size: 26px;
197
+ margin-right: 15px;
198
  cursor: pointer;
 
199
  color: #00d4ff;
200
  }
201
 
202
  .logo {
203
  flex-shrink: 0;
204
+ width: 42px;
205
+ height: 42px;
206
+ border-radius: 12px;
207
  background: linear-gradient(135deg, #00d4ff, #0099ff);
208
  display: flex;
209
  align-items: center;
210
  justify-content: center;
211
+ margin-right: 12px;
 
212
  overflow: hidden;
213
  }
214
 
 
216
  width: 100%;
217
  height: 100%;
218
  object-fit: cover;
 
219
  }
220
 
221
  .title h1 {
222
+ font-size: 20px;
 
223
  background: linear-gradient(135deg, #e8edff, #00d4ff);
224
  -webkit-background-clip: text;
225
  background-clip: text;
 
227
  }
228
 
229
  .title p {
230
+ font-size: 11px;
231
  color: #00d4ff;
232
  display: flex;
233
  align-items: center;
234
+ gap: 4px;
235
  }
236
 
237
  .title p::before {
238
  content: "●";
239
+ font-size: 8px;
240
  color: #00ff88;
 
241
  }
242
 
243
  /* =========================
244
+ CHAT AREA
245
  ========================= */
246
  .chat-area {
247
+ flex: 1;
248
  overflow-y: auto;
249
+ padding: 20px 15px;
250
  background: linear-gradient(180deg, #0a0c15 0%, #0f111a 100%);
251
  -webkit-overflow-scrolling: touch;
252
+ display: flex;
253
+ flex-direction: column;
 
 
 
 
 
 
 
 
 
 
254
  }
255
 
256
  .message {
257
  max-width: 85%;
258
+ padding: 12px 16px;
259
+ border-radius: 18px;
260
+ margin-bottom: 15px;
261
+ font-size: 15px;
262
+ line-height: 1.4;
263
  word-wrap: break-word;
264
+ display: inline-block;
 
 
 
 
 
 
 
 
 
 
 
265
  }
266
 
267
  .bot {
268
  background: rgba(20, 24, 40, 0.9);
 
269
  border: 1px solid rgba(0, 212, 255, 0.2);
270
  color: #d0d9ff;
271
+ border-bottom-left-radius: 4px;
 
272
  align-self: flex-start;
273
  }
274
 
 
276
  background: linear-gradient(135deg, #00d4ff, #0099ff);
277
  color: #0a0c15;
278
  font-weight: 600;
279
+ border-bottom-right-radius: 4px;
280
+ align-self: flex-end;
281
  margin-left: auto;
 
 
282
  }
283
 
284
  /* =========================
285
+ INPUT AREA
286
  ========================= */
287
  .input-area {
288
+ flex-shrink: 0;
289
  display: flex;
290
+ padding: 15px;
291
+ gap: 10px;
292
+ background: #0a0c15;
293
+ border-top: 1px solid rgba(0, 212, 255, 0.15);
294
+ padding-bottom: calc(15px + env(safe-area-inset-bottom));
295
  }
296
 
297
  input {
298
  flex: 1;
299
+ border: 1px solid rgba(0, 212, 255, 0.25);
300
  background: rgba(18, 22, 40, 0.8);
301
+ border-radius: 14px;
302
+ padding: 12px 16px;
303
+ font-size: 16px;
304
  outline: none;
305
  color: #e8edff;
 
306
  }
307
 
308
  input:focus {
309
  border-color: #00d4ff;
 
 
 
 
 
310
  }
311
 
312
  button.send {
 
315
  background: linear-gradient(135deg, #00d4ff, #0099ff);
316
  color: #0a0c15;
317
  font-weight: bold;
318
+ padding: 0 20px;
319
+ border-radius: 14px;
320
+ font-size: 15px;
321
  cursor: pointer;
 
322
  display: flex;
323
  align-items: center;
324
+ }
325
+
326
+ /* =========================
327
+ RESPONSIVE SCREEN
328
+ ======================== */
329
+ @media (max-width: 768px) {
330
+ .sidebar { width: 80%; }
331
+ }
332
+ @media (max-width: 480px) {
333
+ .topbar { height: 60px; }
334
+ .title h1 { font-size: 18px; }
335
+ .message { font-size: 14px; max-width: 90%; }
336
+ }
337
+ </style>
338
+ </head>
339
+ <body>
340
+
341
+ <div class="overlay" id="overlay" onclick="closeSidebar()"></div>
342
+
343
+ <div class="app">
344
+ <!-- SIDEBAR -->
345
+ <div class="sidebar" id="sidebar">
346
+ <div class="sidebar-header">
347
+ <div class="sidebar-logo" id="sidebarLogo">πŸ±β€πŸ‘€</div>
348
+ <div>
349
+ <h2>ChibiCat</h2>
350
+ <p>Neo Intelligence</p>
351
+ </div>
352
+ </div>
353
+ <button class="new-chat" onclick="createNewChat()">+ New Chat</button>
354
+ <div class="chat-history" id="chatHistory"></div>
355
+ </div>
356
+
357
+ <!-- MAIN -->
358
+ <div class="main">
359
+ <!-- TOPBAR -->
360
+ <div class="topbar">
361
+ <div class="menu-btn" onclick="openSidebar()">☰</div>
362
+ <div class="logo" id="mainLogo">πŸ±β€πŸ‘€</div>
363
+ <div class="title">
364
+ <h1>ChibiCat AI</h1>
365
+ <p>Online | Neo Mode</p>
366
+ </div>
367
+ </div>
368
+
369
+ <!-- CHAT AREA -->
370
+ <div class="chat-area" id="chatArea">
371
+ <div class="message bot">
372
+ <span style="font-weight: bold;">⚑ ChibiCat Neo</span><br>
373
+ Halo bro! Ada yang bisa gue bantu? πŸ”₯😎
374
+ </div>
375
+ </div>
376
+
377
+ <!-- INPUT -->
378
+ <div class="input-area">
379
+ <input type="text" id="messageInput" placeholder="Ketik pesan bro..." autocomplete="off" />
380
+ <button class="send" onclick="sendMessage()">Kirim</button>
381
+ </div>
382
+ </div>
383
+ </div>
384
+
385
+ <script>
386
+ let currentChatId = null;
387
+
388
+ const LOGO_CONFIG = {
389
+ mode: "image",
390
+ emoji: "πŸ±β€πŸš€",
391
+ imageUrl: "/static/logo.png",
392
+ imageUrl2: "https://cdn-icons-png.flaticon.com/512/1998/1998592.png"
393
+ };
394
+
395
+ function initLogos() {
396
+ const sidebarLogo = document.getElementById("sidebarLogo");
397
+ const mainLogo = document.getElementById("mainLogo");
398
+ if(!sidebarLogo || !mainLogo) return;
399
+
400
+ if (LOGO_CONFIG.mode === "image") {
401
+ sidebarLogo.innerHTML = `<img src="${LOGO_CONFIG.imageUrl}" class="sidebar-logo-img" onerror="this.src='${LOGO_CONFIG.imageUrl2}'">`;
402
+ sidebarLogo.style.background = "transparent";
403
+ mainLogo.innerHTML = `<img src="${LOGO_CONFIG.imageUrl}" class="logo-img" onerror="this.src='${LOGO_CONFIG.imageUrl2}'">`;
404
+ mainLogo.style.background = "transparent";
405
+ }
406
+ }
407
+
408
+ function openSidebar() {
409
+ document.getElementById("sidebar").classList.add("active");
410
+ document.getElementById("overlay").classList.add("active");
411
+ }
412
+
413
+ function closeSidebar() {
414
+ document.getElementById("sidebar").classList.remove("active");
415
+ document.getElementById("overlay").classList.remove("active");
416
+ }
417
+
418
+ async function createNewChat() {
419
+ try {
420
+ const response = await fetch("/new_chat", { method: "POST" });
421
+ const data = await response.json();
422
+ currentChatId = data.chat_id;
423
+ } catch(e) { console.log("Offline mode handling"); }
424
+
425
+ document.getElementById("chatArea").innerHTML = `
426
+ <div class="message bot">
427
+ <span style="font-weight: bold;">⚑ ChibiCat Neo</span><br>
428
+ Halo bro! Ada yang bisa gue bantu? πŸ”₯😎
429
+ </div>
430
+ `;
431
+ loadChats();
432
+ closeSidebar();
433
+ }
434
+
435
+ async function loadChats() {
436
+ try {
437
+ const response = await fetch("/get_chats");
438
+ const chats = await response.json();
439
+ const history = document.getElementById("chatHistory");
440
+ if(!history || !Array.isArray(chats)) return;
441
+ history.innerHTML = "";
442
+ chats.forEach(chat => {
443
+ history.innerHTML += `
444
+ <div class="history-item" onclick="loadChat('${chat.chat_id}')">
445
+ πŸ’¬ ${escapeHtml(chat.title)}
446
+ </div>
447
+ `;
448
+ });
449
+ } catch (e) { console.log("No histories found"); }
450
+ }
451
+
452
+ async function loadChat(chatId) {
453
+ currentChatId = chatId;
454
+ try {
455
+ const response = await fetch(`/load_chat/${chatId}`);
456
+ const messages = await response.json();
457
+ const chatArea = document.getElementById("chatArea");
458
+ if(!chatArea || !Array.isArray(messages)) return;
459
+ chatArea.innerHTML = "";
460
+ messages.forEach(msg => {
461
+ const role = msg.role === "user" ? "user" : "bot";
462
+ chatArea.innerHTML += `<div class="message ${role}">${escapeHtml(msg.content)}</div>`;
463
+ });
464
+ } catch(e) { console.log("Chat failed to load"); }
465
+ closeSidebar();
466
+ }
467
+
468
+ async function sendMessage() {
469
+ const input = document.getElementById("messageInput");
470
+ const message = input.value.trim();
471
+ if (message === "") return;
472
+
473
+ const chatArea = document.getElementById("chatArea");
474
+ chatArea.innerHTML += `<div class="message user">${escapeHtml(message)}</div>`;
475
+ input.value = "";
476
+ chatArea.scrollTop = chatArea.scrollHeight;
477
+
478
+ try {
479
+ const response = await fetch("/chat", {
480
+ method: "POST",
481
+ headers: { "Content-Type": "application/json" },
482
+ body: JSON.stringify({ message: message })
483
+ });
484
+ const data = await response.json();
485
+ chatArea.innerHTML += `<div class="message bot">${escapeHtml(data.reply)}</div>`;
486
+ chatArea.scrollTop = chatArea.scrollHeight;
487
+ loadChats();
488
+ } catch (error) {
489
+ chatArea.innerHTML += `<div class="message bot">⚠️ Server terputus / offline bro 😭</div>`;
490
+ chatArea.scrollTop = chatArea.scrollHeight;
491
+ }
492
+ }
493
+
494
+ function escapeHtml(text) {
495
+ const div = document.createElement('div');
496
+ div.textContent = text;
497
+ return div.innerHTML;
498
+ }
499
+
500
+ document.getElementById("messageInput").addEventListener("keypress", function(e) {
501
+ if (e.key === "Enter") sendMessage();
502
+ });
503
+
504
+ // Jalankan inisialisasi aman
505
+ initLogos();
506
+ loadChats();
507
+ </script>
508
+
509
+ </body>
510
+ </html>