fast72 commited on
Commit
e6d2c34
·
verified ·
1 Parent(s): bb1af57

Create public/index.html

Browse files
Files changed (1) hide show
  1. public/index.html +99 -0
public/index.html ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html><html lang="id">
2
+ <head>
3
+ <meta charset="UTF-8">
4
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
5
+ <title>AI Chat</title>
6
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/uuid/8.3.2/uuidv4.min.js"></script>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
9
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/github-dark.min.css">
10
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js"></script>
11
+ <style>
12
+ body { background-color: #000; color: #fff; font-family: 'Inter', sans-serif; }
13
+ .chat-container { background-color: #111; border: 1px solid #333; border-radius: 8px; padding: 16px; width: 100%; max-width: 400px; display: flex; flex-direction: column; gap: 8px; }
14
+ .input-field { background-color: #000; color: #fff; border: 1px solid #333; padding: 8px; width: 100%; border-radius: 4px; }
15
+ .message { padding: 6px 12px; border-radius: 12px; max-width: 75%; word-wrap: break-word; }
16
+ .message.user { background-color: #005eff; align-self: flex-end; }
17
+ .message.bot { background-color: #222; align-self: flex-start; }
18
+ .reasoning { color: #888; font-style: italic; }
19
+ .bold { font-weight: bold; }
20
+ .large-text { font-size: 1.2rem; font-weight: bold; }
21
+ .monospace { font-family: monospace; color: #fff; background-color: #333; padding: 2px 4px; border-radius: 4px; }
22
+ .code-block { background-color: #222; padding: 8px; border-radius: 4px; font-family: monospace; white-space: pre-wrap; position: relative; }
23
+ .copy-btn { position: absolute; top: 4px; right: 4px; background: #444; color: #fff; border: none; padding: 2px 6px; cursor: pointer; font-size: 0.8rem; border-radius: 4px; }
24
+ pre code { display: block; padding: 10px; border-radius: 5px; }
25
+ </style>
26
+ </head>
27
+ <body class="flex flex-col items-center justify-center h-screen">
28
+ <div class="chat-container">
29
+ <div id="chat" class="h-64 overflow-y-auto flex flex-col gap-2 pb-2"></div>
30
+ <input id="message" type="text" class="input-field mt-2" placeholder="Ketik pesan..." />
31
+ </div><script>
32
+ const sessionId = uuidv4();
33
+ const chatDiv = document.getElementById('chat');
34
+ const input = document.getElementById('message');
35
+
36
+ input.addEventListener('keypress', async (event) => {
37
+ if (event.key === 'Enter' && input.value.trim() !== '') {
38
+ const message = input.value.trim();
39
+ input.value = '';
40
+ addMessage(message, 'user');
41
+
42
+ const response = await fetch('/chat', {
43
+ method: 'POST',
44
+ headers: { 'Content-Type': 'application/json' },
45
+ body: JSON.stringify({ sessionId, message })
46
+ });
47
+
48
+ if (!response.body) return;
49
+
50
+ const reader = response.body.getReader();
51
+ let botMessage = '';
52
+
53
+ while (true) {
54
+ const { value, done } = await reader.read();
55
+ if (done) break;
56
+
57
+ botMessage += new TextDecoder().decode(value);
58
+ addMessage(botMessage, 'bot', true);
59
+ }
60
+ }
61
+ });
62
+
63
+ function addMessage(text, sender, replaceLast = false) {
64
+ if (replaceLast && chatDiv.lastChild) {
65
+ chatDiv.lastChild.innerHTML = formatMessage(text);
66
+ } else {
67
+ const msgDiv = document.createElement('div');
68
+ msgDiv.classList.add('message', sender);
69
+ msgDiv.innerHTML = formatMessage(text);
70
+ chatDiv.appendChild(msgDiv);
71
+ }
72
+ chatDiv.scrollTop = chatDiv.scrollHeight;
73
+ document.querySelectorAll('pre code').forEach((block) => {
74
+ hljs.highlightElement(block);
75
+ });
76
+ }
77
+
78
+ function formatMessage(text) {
79
+ return text
80
+ .replace(/\*\*(.*?)\*\*/g, '<span class="bold">$1</span>')
81
+ .replace(/### (.*?)\n/g, '<div class="large-text">$1</div>')
82
+ .replace(/`([^`]+)`/g, '<span class="monospace">$1</span>')
83
+ .replace(/```([\s\S]*?)```/g, (match, code) => {
84
+ const escapedCode = code.replace(/</g, '&lt;').replace(/>/g, '&gt;');
85
+ return `<div class="code-block"><button class="copy-btn" onclick="copyCode(this)">Copy</button><pre><code class="language-javascript">${escapedCode}</code></pre></div>`;
86
+ })
87
+ .replace(/<think>(.*?)<\/think>/g, '<span class="reasoning">$1</span>');
88
+ }
89
+
90
+ function copyCode(button) {
91
+ const code = button.nextElementSibling.innerText;
92
+ navigator.clipboard.writeText(code);
93
+ button.innerText = "Copied!";
94
+ setTimeout(() => button.innerText = "Copy", 2000);
95
+ }
96
+ </script>
97
+
98
+ </body>
99
+ </html>