Some checks failed
Host-Based Deploy (Java 21 Fix) / build-and-run (push) Has been cancelled
207 lines
7.7 KiB
HTML
207 lines
7.7 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="de">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<link rel="icon" href="/img/icon.png" type="image/png">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Personen suchen – xXx Sphere</title>
|
||
<link rel="stylesheet" href="/css/variables.css">
|
||
<link rel="stylesheet" href="/css/style.css">
|
||
<style>
|
||
.search-bar {
|
||
display: flex;
|
||
gap: 0.5rem;
|
||
margin-bottom: 1.5rem;
|
||
}
|
||
.search-bar input { flex: 1; }
|
||
.search-bar button { width: auto; margin-top: 0; padding: 0.65rem 1.25rem; }
|
||
|
||
.user-list { list-style: none; margin: 0; padding: 0; }
|
||
.user-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.75rem;
|
||
padding: 0.75rem 0;
|
||
border-bottom: 1px solid var(--color-secondary);
|
||
}
|
||
.user-item:last-child { border-bottom: none; }
|
||
|
||
.user-avatar {
|
||
width: 42px; height: 42px;
|
||
border-radius: 50%;
|
||
background: var(--color-secondary);
|
||
display: flex; align-items: center; justify-content: center;
|
||
font-size: 1.2rem;
|
||
flex-shrink: 0;
|
||
overflow: hidden;
|
||
border: 1px solid var(--color-secondary);
|
||
}
|
||
.user-avatar img { width: 100%; height: 100%; object-fit: cover; }
|
||
|
||
.user-name { font-weight: 600; flex: 1; }
|
||
|
||
.user-actions { display: flex; gap: 0.5rem; flex-shrink: 0; flex-wrap: wrap; justify-content: flex-end; }
|
||
.user-actions button, .user-actions a.btn {
|
||
margin-top: 0;
|
||
padding: 0.35rem 0.75rem;
|
||
font-size: 0.8rem;
|
||
width: auto;
|
||
}
|
||
|
||
.user-profile-link {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.75rem;
|
||
flex: 1;
|
||
min-width: 0;
|
||
text-decoration: none;
|
||
color: inherit;
|
||
}
|
||
.user-profile-link:hover .user-name { color: var(--color-primary); }
|
||
|
||
.hint { color: var(--color-muted); font-size: 0.9rem; margin-top: 0.5rem; }
|
||
</style>
|
||
</head>
|
||
<body class="app">
|
||
|
||
<div class="main">
|
||
<div class="content">
|
||
<h1 style="margin-bottom: 1.25rem;">Personen suchen</h1>
|
||
|
||
<div class="search-bar">
|
||
<input type="text" id="searchInput" placeholder="Name eingeben (mind. 2 Zeichen)…" autocomplete="off">
|
||
<button onclick="doSearch()">Suchen</button>
|
||
</div>
|
||
|
||
<ul class="user-list" id="resultList"></ul>
|
||
<p class="hint" id="hint">Gib mindestens 2 Zeichen ein, um zu suchen.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<script src="/js/icons.js"></script>
|
||
<script src="/js/nav.js"></script>
|
||
<script src="/js/social-sidebar.js"></script>
|
||
<script>
|
||
let debounceTimer;
|
||
|
||
document.getElementById('searchInput').addEventListener('input', function () {
|
||
clearTimeout(debounceTimer);
|
||
const q = this.value.trim();
|
||
if (q.length < 2) {
|
||
document.getElementById('resultList').innerHTML = '';
|
||
document.getElementById('hint').textContent = 'Gib mindestens 2 Zeichen ein, um zu suchen.';
|
||
document.getElementById('hint').style.display = '';
|
||
return;
|
||
}
|
||
document.getElementById('hint').style.display = 'none';
|
||
debounceTimer = setTimeout(doSearch, 400);
|
||
});
|
||
|
||
document.getElementById('searchInput').addEventListener('keydown', e => {
|
||
if (e.key === 'Enter') { clearTimeout(debounceTimer); doSearch(); }
|
||
});
|
||
|
||
async function doSearch() {
|
||
const q = document.getElementById('searchInput').value.trim();
|
||
if (q.length < 2) return;
|
||
try {
|
||
const res = await fetch('/social/users/search?q=' + encodeURIComponent(q));
|
||
if (!res.ok) return;
|
||
renderResults(await res.json());
|
||
} catch (e) { console.error(e); }
|
||
}
|
||
|
||
function renderResults(users) {
|
||
const list = document.getElementById('resultList');
|
||
const hint = document.getElementById('hint');
|
||
list.innerHTML = '';
|
||
if (users.length === 0) {
|
||
hint.textContent = 'Keine Ergebnisse gefunden.';
|
||
hint.style.display = '';
|
||
return;
|
||
}
|
||
hint.style.display = 'none';
|
||
users.forEach(u => {
|
||
const avatar = u.profilePicture
|
||
? `<img src="data:image/png;base64,${u.profilePicture}" alt="">`
|
||
: '◉';
|
||
list.insertAdjacentHTML('beforeend', `
|
||
<li class="user-item" data-user-id="${u.userId}">
|
||
<a href="/community/benutzer.html?userId=${u.userId}" class="user-profile-link">
|
||
<div class="user-avatar">${avatar}</div>
|
||
<div class="user-name">${esc(u.name)}</div>
|
||
</a>
|
||
<div class="user-actions">${buildActions(u)}</div>
|
||
</li>`);
|
||
});
|
||
}
|
||
|
||
function buildActions(u) {
|
||
if (u.friendStatus === 'FRIEND') {
|
||
return `<a href="/community/nachrichten.html?userId=${u.userId}" class="btn" style="background:var(--color-secondary); color:var(--color-text);">✉ Nachricht</a>`;
|
||
}
|
||
if (u.friendStatus === 'PENDING_SENT') {
|
||
return `<button disabled>Anfrage gesendet</button>`;
|
||
}
|
||
if (u.friendStatus === 'PENDING_RECEIVED') {
|
||
return `<button onclick="acceptByUserId('${u.userId}', this)">✓ Annehmen</button>`;
|
||
}
|
||
return `<button onclick="sendRequest('${u.userId}', this)">+ Freund hinzufügen</button>`;
|
||
}
|
||
|
||
async function sendRequest(receiverId, btn) {
|
||
btn.disabled = true;
|
||
btn.textContent = 'Wird gesendet…';
|
||
try {
|
||
const res = await fetch('/social/friends/request', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({ receiverId })
|
||
});
|
||
btn.textContent = (res.ok || res.status === 201 || res.status === 409) ? 'Anfrage gesendet' : 'Fehler';
|
||
} catch (e) {
|
||
btn.disabled = false;
|
||
btn.textContent = '+ Freund hinzufügen';
|
||
}
|
||
}
|
||
|
||
async function acceptByUserId(senderId, btn) {
|
||
btn.disabled = true;
|
||
btn.textContent = '…';
|
||
try {
|
||
const pendingRes = await fetch('/social/friends/pending');
|
||
const pending = await pendingRes.json();
|
||
const f = pending.find(p => p.user.userId === senderId);
|
||
if (!f) { btn.textContent = 'Fehler'; return; }
|
||
|
||
const res = await fetch('/social/friends/accept', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({ friendshipId: f.friendshipId })
|
||
});
|
||
if (res.ok) {
|
||
btn.textContent = '✓ Freund';
|
||
const item = btn.closest('.user-item');
|
||
if (item) {
|
||
item.querySelector('.user-actions').innerHTML =
|
||
`<a href="/community/nachrichten.html?userId=${senderId}" class="btn" style="background:var(--color-secondary); color:var(--color-text);">✉ Nachricht</a>`;
|
||
}
|
||
} else {
|
||
btn.disabled = false;
|
||
btn.textContent = '✓ Annehmen';
|
||
}
|
||
} catch (e) {
|
||
btn.disabled = false;
|
||
btn.textContent = '✓ Annehmen';
|
||
}
|
||
}
|
||
|
||
function esc(s) {
|
||
const d = document.createElement('div');
|
||
d.textContent = s;
|
||
return d.innerHTML;
|
||
}
|
||
</script>
|
||
</body>
|
||
</html>
|