update frontend

This commit is contained in:
2026-06-14 18:00:49 +07:00
parent 7922980975
commit e167363cb1
3 changed files with 104 additions and 16 deletions
+17
View File
@@ -10,6 +10,21 @@ marked.setOptions({
mangle: false, mangle: false,
}); });
// ---- Theme ----
function initTheme() {
const saved = localStorage.getItem('rag-theme') || 'dark';
document.documentElement.setAttribute('data-theme', saved);
}
function toggleTheme() {
const current = document.documentElement.getAttribute('data-theme');
const next = current === 'dark' ? 'light' : 'dark';
document.documentElement.setAttribute('data-theme', next);
localStorage.setItem('rag-theme', next);
}
initTheme();
// DOM // DOM
const sessionList = document.getElementById('session-list'); const sessionList = document.getElementById('session-list');
const messages = document.getElementById('messages'); const messages = document.getElementById('messages');
@@ -21,6 +36,7 @@ const btnNewSession = document.getElementById('btn-new-session');
const btnClear = document.getElementById('btn-clear'); const btnClear = document.getElementById('btn-clear');
const btnDelete = document.getElementById('btn-delete'); const btnDelete = document.getElementById('btn-delete');
const btnMenu = document.getElementById('btn-menu'); const btnMenu = document.getElementById('btn-menu');
const btnTheme = document.getElementById('btn-theme');
const chatTitle = document.getElementById('chat-title'); const chatTitle = document.getElementById('chat-title');
const statsEl = document.getElementById('stats'); const statsEl = document.getElementById('stats');
@@ -232,6 +248,7 @@ btnNewSession.onclick = createSession;
btnClear.onclick = clearMessages; btnClear.onclick = clearMessages;
btnDelete.onclick = deleteSession; btnDelete.onclick = deleteSession;
btnSend.onclick = sendMessage; btnSend.onclick = sendMessage;
btnTheme.onclick = toggleTheme;
btnMenu.onclick = () => { btnMenu.onclick = () => {
document.getElementById('sidebar').classList.toggle('open'); document.getElementById('sidebar').classList.toggle('open');
+73 -12
View File
@@ -1,3 +1,4 @@
/* ===== Dark theme (default) ===== */
:root { :root {
--bg: #0f0f0f; --bg: #0f0f0f;
--bg-sidebar: #161616; --bg-sidebar: #161616;
@@ -18,6 +19,34 @@
--radius: 12px; --radius: 12px;
--radius-sm: 8px; --radius-sm: 8px;
--sidebar-w: 280px; --sidebar-w: 280px;
--footer-bg: #111;
--footer-border: #222;
--code-bg: #0a0a0a;
--table-header: #ffffff08;
}
/* ===== Light theme ===== */
[data-theme="light"] {
--bg: #ffffff;
--bg-sidebar: #f7f7f8;
--bg-chat: #ffffff;
--bg-input: #f0f0f0;
--bg-user: #2563eb;
--bg-assistant: #f4f4f5;
--bg-hover: #ececec;
--bg-active: #2563eb15;
--border: #e0e0e0;
--text: #1a1a1a;
--text-dim: #666;
--text-muted: #999;
--accent: #2563eb;
--accent-hover: #1d4ed8;
--danger: #dc2626;
--danger-hover: #b91c1c;
--footer-bg: #f7f7f8;
--footer-border: #e0e0e0;
--code-bg: #f0f0f0;
--table-header: #00000008;
} }
* { margin: 0; padding: 0; box-sizing: border-box; } * { margin: 0; padding: 0; box-sizing: border-box; }
@@ -35,7 +64,7 @@ body {
height: 100vh; height: 100vh;
} }
/* Sidebar */ /* ===== Sidebar ===== */
.sidebar { .sidebar {
width: var(--sidebar-w); width: var(--sidebar-w);
background: var(--bg-sidebar); background: var(--bg-sidebar);
@@ -59,6 +88,11 @@ body {
font-weight: 600; font-weight: 600;
} }
.sidebar-actions {
display: flex;
gap: 2px;
}
.session-list { .session-list {
flex: 1; flex: 1;
overflow-y: auto; overflow-y: auto;
@@ -111,7 +145,7 @@ body {
line-height: 1.6; line-height: 1.6;
} }
/* Main */ /* ===== Main ===== */
.main { .main {
flex: 1; flex: 1;
display: flex; display: flex;
@@ -139,7 +173,7 @@ body {
gap: 4px; gap: 4px;
} }
/* Messages */ /* ===== Messages ===== */
.messages { .messages {
flex: 1; flex: 1;
overflow-y: auto; overflow-y: auto;
@@ -213,7 +247,7 @@ body {
.bubble li { margin: 2px 0; } .bubble li { margin: 2px 0; }
.bubble code { .bubble code {
background: #ffffff10; background: var(--code-bg);
padding: 1px 5px; padding: 1px 5px;
border-radius: 4px; border-radius: 4px;
font-size: 13px; font-size: 13px;
@@ -221,7 +255,7 @@ body {
} }
.bubble pre { .bubble pre {
background: #0a0a0a; background: var(--code-bg);
border: 1px solid var(--border); border: 1px solid var(--border);
border-radius: var(--radius-sm); border-radius: var(--radius-sm);
padding: 10px 12px; padding: 10px 12px;
@@ -243,9 +277,10 @@ body {
} }
.bubble a { .bubble a {
color: #60a5fa; color: #2563eb;
text-decoration: none; text-decoration: none;
} }
[data-theme="dark"] .bubble a { color: #60a5fa; }
.bubble a:hover { text-decoration: underline; } .bubble a:hover { text-decoration: underline; }
.bubble table { .bubble table {
@@ -259,7 +294,7 @@ body {
padding: 6px 10px; padding: 6px 10px;
text-align: left; text-align: left;
} }
.bubble th { background: #ffffff08; font-weight: 600; } .bubble th { background: var(--table-header); font-weight: 600; }
.bubble strong { font-weight: 600; } .bubble strong { font-weight: 600; }
.bubble em { font-style: italic; } .bubble em { font-style: italic; }
@@ -328,9 +363,9 @@ body {
30% { transform: translateY(-4px); } 30% { transform: translateY(-4px); }
} }
/* Input */ /* ===== Input ===== */
.input-area { .input-area {
padding: 12px 16px 16px; padding: 12px 16px 12px;
border-top: 1px solid var(--border); border-top: 1px solid var(--border);
background: var(--bg-sidebar); background: var(--bg-sidebar);
} }
@@ -390,7 +425,27 @@ body {
margin-top: 6px; margin-top: 6px;
} }
/* Buttons */ /* ===== Footer ===== */
.app-footer {
padding: 10px 16px;
text-align: center;
font-size: 12px;
color: var(--text-muted);
background: var(--footer-bg);
border-top: 1px solid var(--footer-border);
flex-shrink: 0;
}
.app-footer a {
color: var(--accent);
text-decoration: none;
}
.app-footer a:hover {
text-decoration: underline;
}
/* ===== Buttons ===== */
.btn-icon { .btn-icon {
width: 32px; width: 32px;
height: 32px; height: 32px;
@@ -408,13 +463,19 @@ body {
.btn-icon:hover { background: var(--bg-hover); color: var(--text); } .btn-icon:hover { background: var(--bg-hover); color: var(--text); }
.btn-icon.btn-danger:hover { background: var(--danger); color: white; } .btn-icon.btn-danger:hover { background: var(--danger); color: white; }
/* Scrollbar */ /* Theme toggle icons */
[data-theme="dark"] .icon-sun { display: none; }
[data-theme="dark"] .icon-moon { display: block; }
[data-theme="light"] .icon-sun { display: block; }
[data-theme="light"] .icon-moon { display: none; }
/* ===== Scrollbar ===== */
::-webkit-scrollbar { width: 6px; } ::-webkit-scrollbar { width: 6px; }
::-webkit-scrollbar-track { background: transparent; } ::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; } ::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: var(--text-muted); } ::-webkit-scrollbar-thumb:hover { background: var(--text-muted); }
/* Responsive */ /* ===== Responsive ===== */
@media (max-width: 768px) { @media (max-width: 768px) {
.sidebar { .sidebar {
position: fixed; position: fixed;
+14 -4
View File
@@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="vi"> <html lang="vi" data-theme="dark">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
@@ -13,9 +13,15 @@
<aside class="sidebar" id="sidebar"> <aside class="sidebar" id="sidebar">
<div class="sidebar-header"> <div class="sidebar-header">
<h2>Blog RAG</h2> <h2>Blog RAG</h2>
<button class="btn-icon" id="btn-new-session" title="Phiên mới"> <div class="sidebar-actions">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg> <button class="btn-icon" id="btn-theme" title="Chế độ sáng/tối">
</button> <svg class="icon-sun" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></svg>
<svg class="icon-moon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>
</button>
<button class="btn-icon" id="btn-new-session" title="Phiên mới">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
</button>
</div>
</div> </div>
<div class="session-list" id="session-list"></div> <div class="session-list" id="session-list"></div>
<div class="sidebar-footer"> <div class="sidebar-footer">
@@ -60,6 +66,10 @@
</div> </div>
<div class="input-hint">Enter để gửi, Shift+Enter xuống dòng</div> <div class="input-hint">Enter để gửi, Shift+Enter xuống dòng</div>
</div> </div>
<footer class="app-footer">
Copyright &copy; 2026 - Blog RAG Solution - <a href="https://ttaisolutions.com" target="_blank">TTAI Solutions Software</a>
</footer>
</main> </main>
</div> </div>