Browse Source

admin panel chat styles finalized

better text input section with resizing automatically based on the context

synced the background color gradient for empty pages too

size and possision of chat context section enhanced to fit the screen.

chat input sticks to the bottom of chat section

+ small padding and styles improvements
master
Mohsen Taba 2 months ago
parent
commit
a5939ecc6b
  1. 52
      static/css/live_chat.css
  2. 25
      static/js/live_chat.js
  3. 63
      templates/admin/chat/live_chat.html

52
static/css/live_chat.css

@ -24,12 +24,22 @@ html {
width: 100% !important; width: 100% !important;
height: calc(100vh - 140px); height: calc(100vh - 140px);
margin: 0 auto; margin: 0 auto;
display: flex;
gap: 16px;
} }
.rooms-sidebar { .rooms-sidebar {
width: 320px; width: 320px;
background: #FAF6E9; background: #FAF6E9;
/* جایگزین خاکستری ملایم با کرمی */
border: 1px solid rgba(10, 82, 46, 0.15);
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
overflow: hidden;
display: flex;
flex-direction: column;
flex-shrink: 0;
position: relative;
z-index: 20;
} }
@media (min-width: 1024px) { @media (min-width: 1024px) {
@ -40,7 +50,27 @@ html {
.dark .rooms-sidebar { .dark .rooms-sidebar {
background: #052B18; background: #052B18;
/* پس‌زمینه سایدبار در حالت دارک: سبز تیره */
border-color: rgba(250, 246, 233, 0.1);
}
.chat-area {
flex: 1;
display: flex;
flex-direction: column;
position: relative;
z-index: 10;
height: 100%;
min-width: 0;
overflow: hidden;
border: 1px solid rgba(10, 82, 46, 0.15);
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
background: linear-gradient(to bottom, rgba(250, 246, 233, 0.8), rgba(255, 255, 255, 1));
}
.dark .chat-area {
border-color: rgba(250, 246, 233, 0.1);
background: linear-gradient(to bottom, rgba(5, 43, 24, 0.9), rgba(10, 82, 46, 0.4));
} }
/* ── Custom Scrollbar ── */ /* ── Custom Scrollbar ── */
@ -124,6 +154,14 @@ html {
border: none; border: none;
box-shadow: 0 2px 8px rgba(10, 82, 46, 0.2); box-shadow: 0 2px 8px rgba(10, 82, 46, 0.2);
backdrop-filter: blur(20px); backdrop-filter: blur(20px);
height: 64px;
padding: 0 24px;
display: flex;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
flex-shrink: 0;
width: 100%;
} }
.dark .telegram-header { .dark .telegram-header {
@ -132,6 +170,10 @@ html {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
} }
.telegram-header.justify-start {
justify-content: flex-start;
}
.user-avatar { .user-avatar {
width: 40px; width: 40px;
height: 40px; height: 40px;
@ -145,16 +187,14 @@ html {
/* ── Chat Area Background ── */ /* ── Chat Area Background ── */
.chat-messages { .chat-messages {
background: linear-gradient(to bottom, rgba(250, 246, 233, 0.8), rgba(255, 255, 255, 1));
/* پس‌زمینه چت: کرمی محو شونده به سفید */
background: transparent;
overflow-y: auto; overflow-y: auto;
overscroll-behavior: contain; overscroll-behavior: contain;
padding: 1.5rem; padding: 1.5rem;
} }
.dark .chat-messages { .dark .chat-messages {
background: linear-gradient(to bottom, rgba(5, 43, 24, 0.9), rgba(10, 82, 46, 0.4));
/* پس‌زمینه دارک: سبز تیره */
background: transparent;
} }
/* ── Message Bubbles (Telegram Style) ── */ /* ── Message Bubbles (Telegram Style) ── */

25
static/js/live_chat.js

@ -11,6 +11,7 @@ document.addEventListener('DOMContentLoaded', function () {
noChatSelected: document.getElementById('no-chat-selected'), noChatSelected: document.getElementById('no-chat-selected'),
chatHeader: document.getElementById('active-chat-header'), chatHeader: document.getElementById('active-chat-header'),
chatTitle: document.getElementById('active-chat-title'), chatTitle: document.getElementById('active-chat-title'),
chatHeaderInfo: document.getElementById('chat-header-info'),
messages: document.getElementById('chat-messages'), messages: document.getElementById('chat-messages'),
inputArea: document.getElementById('chat-input-area'), inputArea: document.getElementById('chat-input-area'),
form: document.getElementById('chat-form'), form: document.getElementById('chat-form'),
@ -75,7 +76,7 @@ document.addEventListener('DOMContentLoaded', function () {
return ` return `
<div onclick="startChatWithUser(${user.id})" class="room-item flex items-center gap-3 p-3 cursor-pointer"> <div onclick="startChatWithUser(${user.id})" class="room-item flex items-center gap-3 p-3 cursor-pointer">
<div class="room-avatar" style="background: linear-gradient(135deg, #6366f1, #4f46e5); box-shadow: 0 2px 8px rgba(99,102,241,0.3);">
<div class="room-avatar" style="background: linear-gradient(135deg, #0A522E, #052B18); box-shadow: 0 2px 8px rgba(10, 82, 46, 0.3); color: #FAF6E9;">
${initial} ${initial}
</div> </div>
@ -167,10 +168,11 @@ document.addEventListener('DOMContentLoaded', function () {
lastMessageId = 0; lastMessageId = 0;
isFetchingMessages = false; isFetchingMessages = false;
// 🟢 تغییر invisible به hidden برای کارکرد درست بلوک‌ها
UI.noChatSelected.classList.add('hidden'); UI.noChatSelected.classList.add('hidden');
UI.chatHeader.classList.remove('invisible');
UI.messages.classList.remove('invisible');
UI.inputArea.classList.remove('invisible');
UI.chatHeaderInfo.classList.remove('hidden'); // 🟢 تغییر یافته
UI.messages.classList.remove('hidden');
UI.inputArea.classList.remove('hidden');
UI.chatTitle.textContent = title; UI.chatTitle.textContent = title;
UI.messages.innerHTML = '<div class="flex items-center justify-center h-full"><span class="material-symbols-outlined animate-spin text-gray-400 text-3xl">autorenew</span></div>'; UI.messages.innerHTML = '<div class="flex items-center justify-center h-full"><span class="material-symbols-outlined animate-spin text-gray-400 text-3xl">autorenew</span></div>';
@ -246,12 +248,27 @@ document.addEventListener('DOMContentLoaded', function () {
UI.messages.scrollTo({ top: UI.messages.scrollHeight, behavior: 'smooth' }); UI.messages.scrollTo({ top: UI.messages.scrollHeight, behavior: 'smooth' });
} }
// ── Textarea Auto-resize & Key Handling ──
UI.input.addEventListener('input', function() {
this.style.height = 'auto';
this.style.height = (this.scrollHeight) + 'px';
});
UI.input.addEventListener('keydown', function(e) {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
// Trigger form submit
UI.form.dispatchEvent(new Event('submit', { cancelable: true, bubbles: true }));
}
});
UI.form.addEventListener('submit', async (e) => { UI.form.addEventListener('submit', async (e) => {
e.preventDefault(); e.preventDefault();
const text = UI.input.value.trim(); const text = UI.input.value.trim();
if (!text || !currentRoomId) return; if (!text || !currentRoomId) return;
UI.input.value = ''; UI.input.value = '';
UI.input.style.height = 'auto'; // Reset height
try { try {
await fetch(`${window.CHAT_CONFIG.apiUrlSendBase}${currentRoomId}/`, { await fetch(`${window.CHAT_CONFIG.apiUrlSendBase}${currentRoomId}/`, {

63
templates/admin/chat/live_chat.html

@ -37,13 +37,11 @@
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<div
class="chat-main-wrapper flex w-full shadow-md border border-gray-200 dark:border-gray-700 rounded-xl overflow-hidden mt-0 relative">
<div class="chat-main-wrapper flex w-full mt-0 relative">
<div
class="rooms-sidebar flex-shrink-0 flex flex-col border-r border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800/50 relative z-20">
<div class="rooms-sidebar flex-shrink-0 flex flex-col relative z-20">
<div class="telegram-header px-5 py-3 flex-shrink-0 flex items-center justify-between shadow-sm">
<div class="telegram-header shadow-sm">
<div class="flex items-center gap-3"> <div class="flex items-center gap-3">
<div class="user-avatar bg-white/20 border border-white/30 text-white shadow-sm"> <div class="user-avatar bg-white/20 border border-white/30 text-white shadow-sm">
<span class="material-symbols-outlined text-[20px]">forum</span> <span class="material-symbols-outlined text-[20px]">forum</span>
@ -69,20 +67,18 @@
<div id="users-modal" <div id="users-modal"
class="absolute inset-0 z-50 bg-gray-50 dark:bg-gray-900 flex flex-col transform transition-transform duration-300 translate-y-full shadow-2xl"> class="absolute inset-0 z-50 bg-gray-50 dark:bg-gray-900 flex flex-col transform transition-transform duration-300 translate-y-full shadow-2xl">
<div class="telegram-header px-5 py-3 flex items-center gap-3 shadow-sm">
<div class="telegram-header justify-start gap-3 shadow-sm">
<button type="button" id="close-users-modal" <button type="button" id="close-users-modal"
class="text-white hover:bg-white/20 p-1.5 rounded-full transition-colors flex items-center justify-center">
class="text-white hover:bg-white/20 p-1.5 rounded-full transition-colors flex items-center justify-center -ml-2">
<span class="material-symbols-outlined text-[22px]">arrow_back</span> <span class="material-symbols-outlined text-[22px]">arrow_back</span>
</button> </button>
<h3 class="text-[16px] font-semibold text-white m-0 tracking-wide">{% trans "Select Contact" %}</h3> <h3 class="text-[16px] font-semibold text-white m-0 tracking-wide">{% trans "Select Contact" %}</h3>
</div> </div>
<div class="p-4 border-b border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-800 shadow-sm"> <div class="p-4 border-b border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-800 shadow-sm">
<div class="relative telegram-input-container !p-1.5">
<span
class="material-symbols-outlined absolute left-4 top-1/2 -translate-y-1/2 text-gray-400 text-[20px]">search</span>
<input type="text" id="user-search-input"
class="telegram-message-input w-full pl-11 pr-4 py-1 !min-h-[35px]"
<div class="flex items-center telegram-input-container !p-1.5 gap-2">
<span class="material-symbols-outlined text-gray-400 text-[20px] ml-2">search</span>
<input type="text" id="user-search-input" class="telegram-message-input flex-1 py-1 !min-h-[35px]"
placeholder="{% trans 'Search users...' %}"> placeholder="{% trans 'Search users...' %}">
</div> </div>
</div> </div>
@ -95,25 +91,17 @@
</div> </div>
</div> </div>
<div class="chat-area flex-1 flex flex-col relative z-10" style="min-width: 0; overflow: hidden;">
<div id="no-chat-selected"
class="absolute inset-0 flex flex-col items-center justify-center text-gray-400 z-30 bg-[#f8fafc] dark:bg-[#111827]">
<div
class="w-20 h-20 mx-auto mb-6 bg-gradient-to-br from-blue-100 to-blue-200 dark:from-gray-700 dark:to-gray-600 rounded-full flex items-center justify-center shadow-inner">
<span class="material-symbols-outlined text-5xl text-blue-500 dark:text-blue-400 opacity-80">chat</span>
</div>
<h3 class="text-lg font-semibold text-gray-700 dark:text-gray-300 mb-2">{% trans "No Chat Selected" %}</h3>
<p class="text-sm font-medium">{% trans "Select a chat from the sidebar to start messaging" %}</p>
</div>
<div class="chat-area">
<div id="active-chat-header"
class="telegram-header px-6 py-3 flex items-center justify-between flex-shrink-0 invisible">
<div class="flex items-center gap-3">
<div id="active-chat-header" class="telegram-header">
<div id="chat-header-info" class="flex items-center gap-3 hidden">
<div class="user-avatar bg-white/20 border border-white/30 text-white shadow-sm"> <div class="user-avatar bg-white/20 border border-white/30 text-white shadow-sm">
<span class="material-symbols-outlined text-[20px]">group</span> <span class="material-symbols-outlined text-[20px]">group</span>
</div> </div>
<h3 id="active-chat-title" class="text-[16px] font-semibold text-white m-0 tracking-wide"></h3> <h3 id="active-chat-title" class="text-[16px] font-semibold text-white m-0 tracking-wide"></h3>
</div> </div>
<span id="polling-indicator" class="flex h-2.5 w-2.5 relative hidden"> <span id="polling-indicator" class="flex h-2.5 w-2.5 relative hidden">
<span <span
class="animate-ping absolute inline-flex h-full w-full rounded-full bg-green-300 opacity-75"></span> class="animate-ping absolute inline-flex h-full w-full rounded-full bg-green-300 opacity-75"></span>
@ -122,13 +110,26 @@
</span> </span>
</div> </div>
<div id="chat-messages" class="chat-messages flex-1 invisible"></div>
<div id="no-chat-selected"
class="flex-1 flex flex-col items-center justify-center w-full p-8 z-30"
style="transform: translateY(64px);">
<div
class="w-20 h-20 mx-auto mb-6 bg-gradient-to-br from-[#0A522E]/10 to-[#0A522E]/20 dark:from-[#FAF6E9]/10 dark:to-[#FAF6E9]/20 rounded-full flex items-center justify-center shadow-inner">
<span
class="material-symbols-outlined text-5xl text-[#0A522E] dark:text-[#FAF6E9] opacity-90">chat</span>
</div>
<h3 class="text-lg font-semibold text-[#052B18] dark:text-[#FAF6E9] mb-2 text-center">No Chat Selected</h3>
<p class="text-sm font-medium opacity-80 text-[#0A522E] dark:text-[#FAF6E9] text-center">Select a chat from
the sidebar to start messaging</p>
</div>
<div id="chat-messages" class="chat-messages flex-1 hidden"></div>
<div id="chat-input-area" class="message-input-area flex-shrink-0 px-6 py-4 invisible z-20">
<form id="chat-form" class="flex items-center gap-3 w-full m-0 max-w-5xl mx-auto">
<div class="telegram-input-container flex-1">
<input type="text" id="chat-input" class="telegram-message-input w-full"
placeholder="{% trans 'Type your message...' %}" autocomplete="off">
<div id="chat-input-area" class="message-input-area w-full !w-full !max-w-none flex-shrink-0 px-6 py-4 mt-auto hidden z-20">
<form id="chat-form" class="flex items-end gap-3 w-full !w-full !max-w-none m-0">
<div class="telegram-input-container flex-1 w-full flex items-end">
<textarea id="chat-input" class="telegram-message-input w-full resize-none overflow-y-auto chat-scrollbar"
rows="1" placeholder="{% trans 'Type your message...' %}" style="min-height: 24px; max-height: 150px; line-height: 1.5;"></textarea>
</div> </div>
<button type="submit" id="send-btn" class="telegram-action-btn send-btn-telegram shadow-md"> <button type="submit" id="send-btn" class="telegram-action-btn send-btn-telegram shadow-md">
<span class="material-symbols-outlined text-[20px] ml-1">send</span> <span class="material-symbols-outlined text-[20px] ml-1">send</span>

Loading…
Cancel
Save