Skip to content

Commit 8829176

Browse files
Dev NirwalDev Nirwal
authored andcommitted
UI: modernize chat interface with vibrant colors and icons
1 parent c68cebe commit 8829176

1 file changed

Lines changed: 195 additions & 54 deletions

File tree

chat/templates/chat/index.html

Lines changed: 195 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -5,67 +5,199 @@
55
<meta name="viewport" content="width=device-width, initial-scale=1.0">
66
<title>PDF Chat with Gemini</title>
77
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
8+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
89
<style>
9-
body { background-color: #f8f9fa; }
10-
.sidebar { height: 100vh; background-color: #ffffff; border-right: 1px solid #dee2e6; padding: 20px; overflow-y: auto; }
11-
.chat-container { height: 100vh; display: flex; flex-direction: column; }
12-
.chat-messages { flex-grow: 1; padding: 20px; overflow-y: auto; background-color: #ffffff; margin: 20px; border-radius: 10px; border: 1px solid #dee2e6; }
13-
.chat-input { padding: 20px; background-color: #ffffff; border-top: 1px solid #dee2e6; }
14-
.message { margin-bottom: 15px; padding: 10px 15px; border-radius: 15px; max-width: 80%; }
15-
.user-message { background-color: #007bff; color: white; align-self: flex-end; margin-left: auto; }
16-
.bot-message { background-color: #e9ecef; color: #333; align-self: flex-start; }
17-
.loading { font-style: italic; color: #888; }
18-
.pdf-item { cursor: pointer; padding: 10px; border-radius: 5px; margin-bottom: 5px; transition: background 0.3s; }
19-
.pdf-item:hover { background-color: #f1f3f5; }
20-
.pdf-item.active { background-color: #e7f1ff; border: 1px solid #0d6efd; }
10+
body {
11+
background-color: #f0f2f5;
12+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
13+
}
14+
.sidebar {
15+
height: 100vh;
16+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
17+
color: white;
18+
border-right: none;
19+
padding: 25px;
20+
overflow-y: auto;
21+
box-shadow: 2px 0 10px rgba(0,0,0,0.1);
22+
}
23+
.sidebar hr { border-color: rgba(255,255,255,0.2); }
24+
.sidebar h3, .sidebar h5 { font-weight: 600; text-shadow: 1px 1px 2px rgba(0,0,0,0.1); }
25+
.form-label { color: #f8f9fa; }
26+
.form-control { border-radius: 8px; border: none; padding: 10px; }
27+
.btn-primary {
28+
background-color: #ff7e67;
29+
border: none;
30+
border-radius: 8px;
31+
padding: 10px;
32+
font-weight: 600;
33+
transition: all 0.3s ease;
34+
box-shadow: 0 4px 6px rgba(255,126,103,0.3);
35+
}
36+
.btn-primary:hover {
37+
background-color: #ff6b50;
38+
transform: translateY(-2px);
39+
box-shadow: 0 6px 8px rgba(255,126,103,0.4);
40+
}
41+
.chat-container { height: 100vh; display: flex; flex-direction: column; background-color: #f8f9fa;}
42+
.chat-header {
43+
padding: 20px;
44+
background-color: white;
45+
border-bottom: 1px solid #e9ecef;
46+
box-shadow: 0 2px 5px rgba(0,0,0,0.02);
47+
z-index: 10;
48+
}
49+
.chat-messages {
50+
flex-grow: 1;
51+
padding: 25px;
52+
overflow-y: auto;
53+
background-color: transparent;
54+
}
55+
.chat-input {
56+
padding: 20px 30px;
57+
background-color: white;
58+
border-top: 1px solid #e9ecef;
59+
box-shadow: 0 -2px 10px rgba(0,0,0,0.02);
60+
}
61+
.input-group .form-control {
62+
border: 1px solid #ced4da;
63+
padding: 15px 20px;
64+
border-radius: 25px 0 0 25px !important;
65+
box-shadow: inset 0 1px 2px rgba(0,0,0,0.05);
66+
}
67+
.input-group .btn {
68+
border-radius: 0 25px 25px 0 !important;
69+
padding: 0 25px;
70+
background-color: #667eea;
71+
box-shadow: none;
72+
}
73+
.input-group .btn:hover { background-color: #764ba2; }
74+
75+
.message { margin-bottom: 20px; padding: 15px 20px; border-radius: 20px; max-width: 75%; position: relative; font-size: 0.95rem; line-height: 1.5; box-shadow: 0 2px 5px rgba(0,0,0,0.05); }
76+
.user-message {
77+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
78+
color: white;
79+
align-self: flex-end;
80+
margin-left: auto;
81+
border-bottom-right-radius: 5px;
82+
}
83+
.bot-message {
84+
background-color: white;
85+
color: #333;
86+
align-self: flex-start;
87+
border-bottom-left-radius: 5px;
88+
border: 1px solid #e9ecef;
89+
}
90+
.bot-message strong { color: #667eea; }
91+
92+
.loading { font-style: italic; color: #888; background: transparent; border: none; box-shadow: none; }
93+
.loading:after {
94+
content: '...';
95+
animation: dots 1.5s steps(5, end) infinite;
96+
}
97+
@keyframes dots { 0%, 20% { color: rgba(0,0,0,0); text-shadow: .25em 0 0 rgba(0,0,0,0), .5em 0 0 rgba(0,0,0,0);} 40% { color: #888; text-shadow: .25em 0 0 rgba(0,0,0,0), .5em 0 0 rgba(0,0,0,0);} 60% { text-shadow: .25em 0 0 #888, .5em 0 0 rgba(0,0,0,0);} 80%, 100% { text-shadow: .25em 0 0 #888, .5em 0 0 #888;}}
98+
99+
.pdf-item {
100+
cursor: pointer;
101+
padding: 12px 15px;
102+
border-radius: 10px;
103+
margin-bottom: 10px;
104+
transition: all 0.2s;
105+
background-color: rgba(255,255,255,0.1);
106+
border-left: 4px solid transparent;
107+
}
108+
.pdf-item:hover {
109+
background-color: rgba(255,255,255,0.2);
110+
transform: translateX(5px);
111+
}
112+
.pdf-item.active {
113+
background-color: white;
114+
color: #333;
115+
border-left: 4px solid #ff7e67;
116+
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
117+
}
118+
.pdf-item.active .text-muted, .pdf-item.active small { color: #666 !important; }
119+
120+
/* Custom scrollbar for webkit */
121+
::-webkit-scrollbar { width: 8px; }
122+
::-webkit-scrollbar-track { background: transparent; }
123+
::-webkit-scrollbar-thumb { background: rgba(0,0,0,0.2); border-radius: 4px; }
124+
::-webkit-scrollbar-thumb:hover { background: rgba(0,0,0,0.3); }
125+
.sidebar::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.3); }
126+
.sidebar::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.5); }
21127
</style>
22128
</head>
23129
<body>
24-
<div class="container-fluid">
25-
<div class="row">
130+
<div class="container-fluid p-0">
131+
<div class="row g-0">
26132
<!-- Sidebar: PDF List and Upload -->
27-
<div class="col-md-3 sidebar">
28-
<h3>PDF Chat</h3>
29-
<hr>
30-
<h5>Upload PDF</h5>
31-
<form action="{% url 'upload_pdf' %}" method="post" enctype="multipart/form-data" class="mb-4">
32-
{% csrf_token %}
33-
<div class="mb-3">
34-
<label for="id_title" class="form-label">Title</label>
35-
{{ form.title }}
36-
</div>
37-
<div class="mb-3">
38-
<label for="id_file" class="form-label">PDF File</label>
39-
{{ form.file }}
40-
</div>
41-
<button type="submit" class="btn btn-primary w-100">Upload and Process</button>
42-
</form>
43-
<hr>
44-
<h5>Documents</h5>
45-
<div id="pdf-list">
133+
<div class="col-md-3 col-lg-3 sidebar d-flex flex-column">
134+
<div class="mb-4 text-center">
135+
<h3 class="mt-2"><i class="fas fa-file-pdf me-2"></i>DocuChat AI</h3>
136+
<p class="small text-light opacity-75">Powered by Gemini</p>
137+
</div>
138+
139+
<div class="upload-section bg-white bg-opacity-10 p-3 rounded-3 mb-4">
140+
<h5 class="mb-3"><i class="fas fa-cloud-upload-alt me-2"></i>Upload PDF</h5>
141+
<form action="{% url 'upload_pdf' %}" method="post" enctype="multipart/form-data">
142+
{% csrf_token %}
143+
<div class="mb-2">
144+
<input type="text" name="title" class="form-control form-control-sm" placeholder="Document Title" required id="id_title">
145+
</div>
146+
<div class="mb-3">
147+
<input type="file" name="file" class="form-control form-control-sm" required id="id_file" accept=".pdf">
148+
</div>
149+
<button type="submit" class="btn btn-primary w-100 btn-sm"><i class="fas fa-cogs me-1"></i> Process Document</button>
150+
</form>
151+
</div>
152+
153+
<h5 class="mb-3 mt-2"><i class="fas fa-book me-2"></i>My Library</h5>
154+
<div id="pdf-list" class="flex-grow-1 overflow-auto pe-2">
46155
{% for doc in documents %}
47156
<div class="pdf-item {% if doc.status == 'FAILED' %}border-danger{% endif %}" data-id="{{ doc.id }}" data-status="{{ doc.status }}">
48-
<strong>{{ doc.title }}</strong><br>
49-
<small class="text-muted">{{ doc.uploaded_at|date:"M d, Y H:i" }}</small><br>
50-
<small class="{% if doc.status == 'COMPLETED' %}text-success{% elif doc.status == 'FAILED' %}text-danger{% else %}text-warning{% endif %}">
51-
Status: {{ doc.get_status_display }}
52-
</small>
157+
<div class="d-flex justify-content-between align-items-center">
158+
<strong class="text-truncate">{{ doc.title }}</strong>
159+
</div>
160+
<small class="text-light opacity-75 d-block mt-1"><i class="far fa-clock me-1"></i>{{ doc.uploaded_at|date:"M d, Y H:i" }}</small>
161+
<div class="mt-1">
162+
{% if doc.status == 'COMPLETED' %}
163+
<span class="badge bg-success bg-opacity-75 text-white border-0"><i class="fas fa-check-circle me-1"></i>Ready</span>
164+
{% elif doc.status == 'FAILED' %}
165+
<span class="badge bg-danger bg-opacity-75 text-white border-0"><i class="fas fa-times-circle me-1"></i>Failed</span>
166+
{% else %}
167+
<span class="badge bg-warning text-dark border-0"><i class="fas fa-spinner fa-spin me-1"></i>Processing</span>
168+
{% endif %}
169+
</div>
53170
</div>
54171
{% empty %}
55-
<p class="text-muted">No documents uploaded yet.</p>
172+
<div class="text-center mt-5 text-light opacity-50">
173+
<i class="fas fa-folder-open fa-3x mb-3"></i>
174+
<p>Your library is empty.<br>Upload a PDF to get started.</p>
175+
</div>
56176
{% endfor %}
57177
</div>
58178
</div>
59179

60180
<!-- Main Chat Area -->
61-
<div class="col-md-9 chat-container">
181+
<div class="col-md-9 col-lg-9 chat-container">
182+
<div class="chat-header d-flex justify-content-between align-items-center">
183+
<h4 class="m-0 text-secondary" id="current-doc-title">Select a document to begin</h4>
184+
<span class="badge bg-primary rounded-pill"><i class="fas fa-robot me-1"></i>Gemini 1.5 Flash</span>
185+
</div>
186+
62187
<div id="chat-messages" class="chat-messages d-flex flex-column">
63-
<div class="message bot-message">Select a document from the left to start chatting!</div>
188+
<div class="text-center mt-5 text-muted">
189+
<i class="fas fa-comments fa-4x mb-3 opacity-25"></i>
190+
<h5>Welcome to DocuChat!</h5>
191+
<p>Select a processed document from the sidebar to ask questions about its content.</p>
192+
</div>
64193
</div>
194+
65195
<div class="chat-input">
66-
<div class="input-group">
67-
<input type="text" id="query-input" class="form-control" placeholder="Ask a question about the document..." disabled>
68-
<button id="send-btn" class="btn btn-primary" type="button" disabled>Send</button>
196+
<div class="input-group input-group-lg shadow-sm rounded-pill">
197+
<input type="text" id="query-input" class="form-control border-0" placeholder="Ask a question about the document..." disabled>
198+
<button id="send-btn" class="btn btn-primary" type="button" disabled>
199+
<i class="fas fa-paper-plane me-1"></i> Send
200+
</button>
69201
</div>
70202
</div>
71203
</div>
@@ -79,19 +211,27 @@ <h5>Documents</h5>
79211
item.addEventListener('click', function() {
80212
const status = this.getAttribute('data-status');
81213
if (status !== 'COMPLETED') {
82-
alert('This document is not ready for chat. Status: ' + status);
214+
alert('This document is not ready for chat yet. Status: ' + status);
83215
return;
84216
}
85217

86218
document.querySelectorAll('.pdf-item').forEach(i => i.classList.remove('active'));
87219
this.classList.add('active');
88220
selectedDocId = this.getAttribute('data-id');
221+
const title = this.querySelector('strong').innerText;
89222

90223
document.getElementById('query-input').disabled = false;
91224
document.getElementById('send-btn').disabled = false;
225+
document.getElementById('query-input').focus();
226+
227+
document.getElementById('current-doc-title').innerHTML = `<i class="fas fa-file-alt me-2 text-primary"></i>${title}`;
92228

93229
const chatMessages = document.getElementById('chat-messages');
94-
chatMessages.innerHTML = `<div class="message bot-message">Now chatting with: <strong>${this.querySelector('strong').innerText}</strong></div>`;
230+
chatMessages.innerHTML = `
231+
<div class="message bot-message shadow-sm">
232+
<i class="fas fa-robot me-2 text-primary"></i>
233+
Hi! I've read <strong>${title}</strong>. What would you like to know about it?
234+
</div>`;
95235
});
96236
});
97237

@@ -104,16 +244,16 @@ <h5>Documents</h5>
104244

105245
// Add user message
106246
const userMsgDiv = document.createElement('div');
107-
userMsgDiv.className = 'message user-message';
247+
userMsgDiv.className = 'message user-message shadow-sm';
108248
userMsgDiv.innerText = query;
109249
chatMessages.appendChild(userMsgDiv);
110250

111251
input.value = '';
112252

113253
// Add loading message
114254
const loadingMsgDiv = document.createElement('div');
115-
loadingMsgDiv.className = 'message bot-message loading';
116-
loadingMsgDiv.innerText = 'Gemini is thinking...';
255+
loadingMsgDiv.className = 'message bot-message loading shadow-sm';
256+
loadingMsgDiv.innerHTML = '<i class="fas fa-robot me-2 text-primary opacity-50"></i>Analyzing document';
117257
chatMessages.appendChild(loadingMsgDiv);
118258
chatMessages.scrollTop = chatMessages.scrollHeight;
119259

@@ -131,19 +271,20 @@ <h5>Documents</h5>
131271
chatMessages.removeChild(loadingMsgDiv);
132272

133273
const botMsgDiv = document.createElement('div');
134-
botMsgDiv.className = 'message bot-message';
274+
botMsgDiv.className = 'message bot-message shadow-sm';
275+
135276
if (data.answer) {
136-
botMsgDiv.innerText = data.answer;
277+
botMsgDiv.innerHTML = `<i class="fas fa-robot me-2 text-primary"></i>${data.answer.replace(/\n/g, '<br>')}`;
137278
} else {
138-
botMsgDiv.innerText = 'Error: ' + (data.error || 'Unknown error');
279+
botMsgDiv.innerHTML = `<i class="fas fa-exclamation-triangle me-2 text-danger"></i>Error: ${data.error || 'Unknown error'}`;
139280
}
140281
chatMessages.appendChild(botMsgDiv);
141282

142283
} catch (error) {
143284
chatMessages.removeChild(loadingMsgDiv);
144285
const botMsgDiv = document.createElement('div');
145-
botMsgDiv.className = 'message bot-message text-danger';
146-
botMsgDiv.innerText = 'Error: Failed to connect to server.';
286+
botMsgDiv.className = 'message bot-message border-danger text-danger shadow-sm';
287+
botMsgDiv.innerHTML = `<i class="fas fa-exclamation-triangle me-2"></i>Connection error. Please try again.`;
147288
chatMessages.appendChild(botMsgDiv);
148289
}
149290

0 commit comments

Comments
 (0)