feat: gestión de amigos y mejora visual del dropdown de búsqueda
- FriendshipController: carga también amigos aceptados con su friendship - friendships/index: tabs con 'Mis amigos' (tabla con Mensaje/Quitar) y 'Solicitudes' - Notificaciones de solicitud abren directamente la pestaña de solicitudes (#solicitudes) - Dropdown de búsqueda: bordes redondeados, sombra suave, margen superior, hover en items, etiqueta de sección y separadores finos Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -17,8 +17,12 @@
|
||||
<span class="btn btn-primary"><i class="fas fa-search fa-sm"></i></span>
|
||||
</div>
|
||||
</div>
|
||||
<div id="search-results" class="shadow bg-white rounded position-absolute w-100 d-none"
|
||||
style="top:100%; left:0; z-index:9999; max-height:320px; overflow-y:auto"></div>
|
||||
<div id="search-results" class="bg-white position-absolute d-none"
|
||||
style="top:calc(100% + 6px); left:0; right:0; z-index:9999;
|
||||
max-height:340px; overflow-y:auto;
|
||||
border:1px solid rgba(0,0,0,.1); border-radius:8px;
|
||||
box-shadow:0 8px 24px rgba(0,0,0,.12);
|
||||
min-width:300px"></div>
|
||||
</div>
|
||||
|
||||
<ul class="navbar-nav ml-auto">
|
||||
@@ -173,6 +177,13 @@
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<style>
|
||||
.search-result-item { transition: background .15s; }
|
||||
.search-result-item:hover { background: #f8f9fc; }
|
||||
#search-results > div:first-child { border-radius: 8px 8px 0 0; }
|
||||
#search-results > div:last-child { border-radius: 0 0 8px 8px; }
|
||||
</style>
|
||||
|
||||
<script>
|
||||
// ── Mensajes en tiempo real ──────────────────────────────
|
||||
function updateBadge(id, increment) {
|
||||
@@ -311,32 +322,48 @@ function markAllNotifsRead() {
|
||||
|
||||
function renderResults(users) {
|
||||
if (!users.length) {
|
||||
results.innerHTML = '<div class="p-3 text-muted small text-center">Sin resultados</div>';
|
||||
results.innerHTML = `
|
||||
<div class="px-4 py-3 text-center">
|
||||
<i class="fas fa-search text-muted mb-2 d-block" style="font-size:1.4rem"></i>
|
||||
<span class="text-muted small">Sin resultados</span>
|
||||
</div>`;
|
||||
results.classList.remove('d-none');
|
||||
return;
|
||||
}
|
||||
results.innerHTML = users.map(u => {
|
||||
const btn = friendshipLabel(u.friendship);
|
||||
return `
|
||||
<div class="d-flex align-items-center px-3 py-2 border-bottom search-result-item">
|
||||
<a href="${u.profile_url}" class="d-flex align-items-center flex-grow-1 text-dark text-decoration-none">
|
||||
<img src="${u.avatar}" class="rounded-circle mr-2" width="36" height="36" style="object-fit:cover">
|
||||
<span class="font-weight-bold small">${u.name}</span>
|
||||
</a>
|
||||
<div class="d-flex align-items-center" style="gap:.4rem">
|
||||
<button class="btn btn-sm ${btn.cls} friend-toggle-btn"
|
||||
data-user-id="${u.id}"
|
||||
data-friendship-id="${u.friendship.id ?? ''}"
|
||||
data-status="${u.friendship.status}"
|
||||
data-is-receiver="${u.friendship.is_receiver}">
|
||||
<i class="fas ${btn.icon} mr-1"></i>${btn.label}
|
||||
</button>
|
||||
${u.friendship.status === 'accepted'
|
||||
? `<a href="${u.chat_url}" class="btn btn-sm btn-outline-primary"><i class="fas fa-comment"></i></a>`
|
||||
: ''}
|
||||
</div>
|
||||
</div>`;
|
||||
}).join('');
|
||||
results.innerHTML =
|
||||
`<div class="px-3 pt-2 pb-1" style="font-size:.7rem;font-weight:600;letter-spacing:.05em;color:#aaa;text-transform:uppercase">Personas</div>` +
|
||||
users.map((u, i) => {
|
||||
const btn = friendshipLabel(u.friendship);
|
||||
const isLast = i === users.length - 1;
|
||||
return `
|
||||
<div class="d-flex align-items-center px-3 py-2 search-result-item"
|
||||
style="${!isLast ? 'border-bottom:1px solid #f1f1f1' : ''}">
|
||||
<a href="${u.profile_url}"
|
||||
class="d-flex align-items-center flex-grow-1 text-dark text-decoration-none"
|
||||
style="min-width:0">
|
||||
<img src="${u.avatar}" class="rounded-circle flex-shrink-0 mr-3"
|
||||
width="38" height="38" style="object-fit:cover">
|
||||
<span class="font-weight-bold small text-truncate">${u.name}</span>
|
||||
</a>
|
||||
<div class="d-flex align-items-center flex-shrink-0 ml-2" style="gap:.35rem">
|
||||
<button class="btn btn-sm ${btn.cls} friend-toggle-btn rounded-pill"
|
||||
style="font-size:.72rem;padding:.2rem .65rem"
|
||||
data-user-id="${u.id}"
|
||||
data-status="${u.friendship.status}"
|
||||
data-is-receiver="${u.friendship.is_receiver}">
|
||||
<i class="fas ${btn.icon} mr-1"></i>${btn.label}
|
||||
</button>
|
||||
${u.friendship.status === 'accepted'
|
||||
? `<a href="${u.chat_url}"
|
||||
class="btn btn-sm btn-outline-primary rounded-pill"
|
||||
style="font-size:.72rem;padding:.2rem .55rem"
|
||||
title="Enviar mensaje">
|
||||
<i class="fas fa-comment"></i>
|
||||
</a>`
|
||||
: ''}
|
||||
</div>
|
||||
</div>`;
|
||||
}).join('');
|
||||
results.classList.remove('d-none');
|
||||
|
||||
// Bind toggle buttons
|
||||
|
||||
Reference in New Issue
Block a user