BDSM Game umgesetzt, Community Features ergänzt
This commit is contained in:
204
xxxthegame/src/main/resources/static/personen-suchen.html
Normal file
204
xxxthegame/src/main/resources/static/personen-suchen.html
Normal file
@@ -0,0 +1,204 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Personen suchen – XXX The Game</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/sidebar.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="/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="/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="/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>
|
||||
Reference in New Issue
Block a user