diff --git a/static/css/conversations.css b/static/css/conversations.css index c961dbb..c93cdd6 100644 --- a/static/css/conversations.css +++ b/static/css/conversations.css @@ -160,6 +160,15 @@ background: var(--conv-primary-hover); } +.btn-new-group { + background: var(--conv-surface); + color: var(--conv-primary); + border: 1.5px solid var(--conv-primary); +} +.btn-new-group:hover { + background: var(--conv-primary-light); +} + @media (max-width: 768px) { .btn-new-text { display: none; } .btn-new-conversation { width: 36px; padding: 0; } diff --git a/static/js/conversations.js b/static/js/conversations.js index fd3e791..50d60d8 100644 --- a/static/js/conversations.js +++ b/static/js/conversations.js @@ -2201,6 +2201,246 @@ }, }; + // ============================================================ + // 10b. NEW GROUP MODAL + // ============================================================ + + var NewGroupModal = { + _quill: null, + _selectedMembers: [], + _debounceTimer: null, + + init: function () { + var btn = document.getElementById('newGroupBtn'); + var modal = document.getElementById('newGroupModal'); + if (!btn || !modal) return; + + btn.addEventListener('click', function () { + NewGroupModal.open(); + }); + + var closeBtn = document.getElementById('closeNewGroup'); + var cancelBtn = document.getElementById('cancelNewGroup'); + if (closeBtn) closeBtn.addEventListener('click', function () { modal.style.display = 'none'; }); + if (cancelBtn) cancelBtn.addEventListener('click', function () { modal.style.display = 'none'; }); + + var sendBtn = document.getElementById('sendNewGroup'); + if (sendBtn) sendBtn.addEventListener('click', function () { NewGroupModal.send(); }); + + var searchInput = document.getElementById('groupRecipientSearch'); + if (searchInput) { + searchInput.addEventListener('input', function () { + clearTimeout(NewGroupModal._debounceTimer); + NewGroupModal._debounceTimer = setTimeout(function () { + NewGroupModal.filterRecipients(searchInput.value); + }, 200); + }); + } + }, + + open: function () { + NewGroupModal._selectedMembers = []; + var nameInput = document.getElementById('groupNameInput'); + if (nameInput) nameInput.value = ''; + var searchInput = document.getElementById('groupRecipientSearch'); + if (searchInput) searchInput.value = ''; + var suggestions = document.getElementById('groupRecipientSuggestions'); + if (suggestions) suggestions.innerHTML = ''; + var selected = document.getElementById('groupSelectedRecipients'); + if (selected) selected.innerHTML = ''; + + var editorEl = document.getElementById('groupMessageEditor'); + if (editorEl) { + editorEl.innerHTML = ''; + NewGroupModal._quill = new Quill('#groupMessageEditor', { + theme: 'snow', + placeholder: 'Pierwsza wiadomość (opcjonalna)...', + modules: { + toolbar: [['bold', 'italic'], ['link'], ['clean']], + }, + }); + } + + var modal = document.getElementById('newGroupModal'); + if (modal) modal.style.display = 'flex'; + if (nameInput) nameInput.focus(); + }, + + filterRecipients: async function (query) { + var suggestions = document.getElementById('groupRecipientSuggestions'); + if (!suggestions) return; + suggestions.innerHTML = ''; + + query = (query || '').trim(); + if (query.length < 2) return; + + suggestions.innerHTML = '
Szukam...
'; + + try { + var resp = await fetch('/api/users/search?q=' + encodeURIComponent(query), { + headers: { 'X-CSRFToken': window.__CSRF_TOKEN__ }, + }); + if (!resp.ok) throw new Error('search failed'); + var users = await resp.json(); + + suggestions.innerHTML = ''; + var selectedIds = NewGroupModal._selectedMembers.map(function (r) { return r.id; }); + var matches = users.filter(function (u) { + return selectedIds.indexOf(u.id) === -1; + }); + + if (!matches.length) { + suggestions.innerHTML = '
Brak wyników
'; + return; + } + + matches.forEach(function (u) { + var item = el('div', 'suggestion-item'); + item.style.padding = '8px 12px'; + item.style.cursor = 'pointer'; + item.style.display = 'flex'; + item.style.alignItems = 'center'; + item.style.gap = '8px'; + item.style.borderBottom = '1px solid var(--conv-border)'; + + var avatar = el('div', 'conv-avatar ' + avatarColor(u.name)); + avatar.style.width = '30px'; + avatar.style.height = '30px'; + avatar.style.minWidth = '30px'; + avatar.style.fontSize = '11px'; + avatar.textContent = initials(u.name); + + var info = el('div', ''); + var nameEl = el('div', '', u.name || u.email); + nameEl.style.fontSize = '14px'; + nameEl.style.fontWeight = '500'; + if (u.company_name) { + var companyEl = el('div', '', u.company_name); + companyEl.style.fontSize = '12px'; + companyEl.style.color = 'var(--conv-text-muted)'; + info.appendChild(nameEl); + info.appendChild(companyEl); + } else { + info.appendChild(nameEl); + } + + item.appendChild(avatar); + item.appendChild(info); + + item.addEventListener('click', function () { + NewGroupModal.selectMember(u); + }); + item.addEventListener('mouseenter', function () { + item.style.background = 'var(--conv-surface-secondary)'; + }); + item.addEventListener('mouseleave', function () { + item.style.background = ''; + }); + + suggestions.appendChild(item); + }); + } catch (e) { + suggestions.innerHTML = '
Błąd wyszukiwania
'; + } + }, + + selectMember: function (user) { + NewGroupModal._selectedMembers.push(user); + + var container = document.getElementById('groupSelectedRecipients'); + if (container) { + var pill = el('span', ''); + pill.style.display = 'inline-flex'; + pill.style.alignItems = 'center'; + pill.style.gap = '4px'; + pill.style.padding = '4px 10px'; + pill.style.borderRadius = '16px'; + pill.style.background = 'var(--conv-primary-light)'; + pill.style.fontSize = '13px'; + pill.style.color = 'var(--conv-text-primary)'; + pill.style.margin = '2px'; + + pill.textContent = user.name || user.email; + var removeBtn = el('button', '', '\u00d7'); + removeBtn.style.border = 'none'; + removeBtn.style.background = 'transparent'; + removeBtn.style.cursor = 'pointer'; + removeBtn.style.fontSize = '14px'; + removeBtn.style.color = 'var(--conv-text-muted)'; + removeBtn.style.padding = '0'; + removeBtn.style.lineHeight = '1'; + removeBtn.addEventListener('click', function () { + NewGroupModal._selectedMembers = NewGroupModal._selectedMembers.filter(function (r) { + return r.id !== user.id; + }); + pill.remove(); + }); + pill.appendChild(removeBtn); + container.appendChild(pill); + } + + var searchInput = document.getElementById('groupRecipientSearch'); + if (searchInput) searchInput.value = ''; + var suggestions = document.getElementById('groupRecipientSuggestions'); + if (suggestions) suggestions.innerHTML = ''; + if (searchInput) searchInput.focus(); + }, + + send: async function () { + var nameInput = document.getElementById('groupNameInput'); + var groupName = (nameInput ? nameInput.value : '').trim(); + + if (NewGroupModal._selectedMembers.length < 2) { + alert('Wybierz co najmniej dwóch członków grupy'); + return; + } + + if (state._isCreating) return; + state._isCreating = true; + + var messageContent = ''; + if (NewGroupModal._quill) { + var text = NewGroupModal._quill.getText().trim(); + if (text) { + messageContent = NewGroupModal._quill.root.innerHTML; + } + } + + var memberIds = NewGroupModal._selectedMembers.map(function (r) { return r.id; }); + + // Auto-generate name if not provided + if (!groupName) { + var names = NewGroupModal._selectedMembers.map(function (r) { return r.name || r.email; }); + names.push(window.__CURRENT_USER__.name); + groupName = names.join(', '); + } + + try { + var result = await api('/api/conversations', 'POST', { + member_ids: memberIds, + name: groupName, + message: messageContent, + }); + + var modal = document.getElementById('newGroupModal'); + if (modal) modal.style.display = 'none'; + + var existing = state.conversations.find(function (c) { return c.id === result.id; }); + if (!existing) { + state.conversations.unshift(result); + } else { + Object.assign(existing, result); + } + ConversationList.renderList(); + ConversationList.selectConversation(result.id); + } catch (e) { + alert('Nie udało się utworzyć grupy: ' + e.message); + } finally { + state._isCreating = false; + } + }, + }; + // ============================================================ // 11. SEARCH // ============================================================ @@ -2571,6 +2811,7 @@ ConversationList.renderList(); Composer.init(); NewMessageModal.init(); + NewGroupModal.init(); Search.init(); Pins.init(); initContextMenu(); diff --git a/templates/messages/conversations.html b/templates/messages/conversations.html index 0f8388a..f96a37e 100644 --- a/templates/messages/conversations.html +++ b/templates/messages/conversations.html @@ -5,7 +5,7 @@ {% block head_extra %} - +