Some checks failed
Host-Based Deploy (Java 21 Fix) / build-and-run (push) Has been cancelled
160 lines
6.7 KiB
HTML
160 lines
6.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>Home – xXx Sphere</title>
|
||
<link rel="stylesheet" href="/css/variables.css">
|
||
<link rel="stylesheet" href="/css/style.css">
|
||
<style>
|
||
.game-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
||
gap: 1.25rem;
|
||
margin-top: 1.5rem;
|
||
}
|
||
.game-card {
|
||
background: var(--color-secondary);
|
||
border: 1px solid var(--color-secondary);
|
||
border-radius: 12px;
|
||
padding: 1.5rem 1.25rem;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 0.75rem;
|
||
}
|
||
.game-card-icon { font-size: 2rem; line-height: 1; }
|
||
.game-card-title { font-size: 1.1rem; font-weight: 700; margin: 0; }
|
||
.game-card-desc { font-size: 0.88rem; color: var(--color-muted); line-height: 1.6; flex: 1; }
|
||
.game-card-btn { margin-top: 0.25rem; width: auto; align-self: flex-start; padding: 0.5rem 1.25rem; }
|
||
.welcome { font-size: 0.95rem; color: var(--color-muted); margin: 0.25rem 0 0; }
|
||
|
||
.section-label {
|
||
font-size: 0.8rem; font-weight: 600; color: var(--color-muted);
|
||
text-transform: uppercase; letter-spacing: 0.05em;
|
||
margin: 2rem 0 0.75rem;
|
||
padding-bottom: 0.5rem;
|
||
border-bottom: 1px solid var(--color-secondary);
|
||
}
|
||
.visitors-strip {
|
||
display: flex; flex-wrap: wrap; gap: 0.75rem;
|
||
}
|
||
.visitor-card {
|
||
display: flex; flex-direction: column; align-items: center; gap: 0.3rem;
|
||
text-decoration: none; color: var(--color-text);
|
||
width: 72px;
|
||
}
|
||
.visitor-card:hover .visitor-avatar { border-color: var(--color-primary); }
|
||
.visitor-avatar {
|
||
width: 56px; height: 56px; border-radius: 50%;
|
||
background: var(--color-secondary);
|
||
border: 2px solid var(--color-secondary);
|
||
display: flex; align-items: center; justify-content: center;
|
||
font-size: 1.4rem; overflow: hidden; flex-shrink: 0;
|
||
transition: border-color 0.15s;
|
||
}
|
||
.visitor-avatar img { width: 100%; height: 100%; object-fit: cover; border-radius: 50%; }
|
||
.visitor-name {
|
||
font-size: 0.75rem; text-align: center;
|
||
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
||
width: 100%;
|
||
}
|
||
.visitor-time { font-size: 0.68rem; color: var(--color-muted); text-align: center; }
|
||
</style>
|
||
</head>
|
||
<body class="app">
|
||
<div class="main">
|
||
<div class="content">
|
||
<h1 style="margin:0 0 0.15rem;">Home</h1>
|
||
<p class="welcome" id="greeting"></p>
|
||
|
||
<div class="game-grid">
|
||
<div class="game-card">
|
||
<div class="game-card-icon">♡</div>
|
||
<h2 class="game-card-title">Vanilla Game</h2>
|
||
<p class="game-card-desc">
|
||
Entdecke spielerische Rollenspiele und Aufgaben in einem entspannten Rahmen.
|
||
Ideal für den Einstieg – ohne Regeln, nur Spaß zu zweit oder in der Gruppe.
|
||
</p>
|
||
<a href="/games/vanilla/sessionvanilla.html"><button class="game-card-btn">Neue Session starten</button></a>
|
||
</div>
|
||
|
||
<div class="game-card">
|
||
<div class="game-card-icon">◆</div>
|
||
<h2 class="game-card-title">BDSM Game</h2>
|
||
<p class="game-card-desc">
|
||
Tauche ein in strukturierte Sessions mit Aufgaben, Toys und klaren Rollen.
|
||
Definiere Grenzen, vergib Aufgaben und erlebe intensive Momente mit deinem Partner.
|
||
</p>
|
||
<a href="/games/bdsm/neubdsm.html"><button class="game-card-btn">Neue Session starten</button></a>
|
||
</div>
|
||
|
||
<div class="game-card">
|
||
<div class="game-card-icon">⊗</div>
|
||
<h2 class="game-card-title">Chastity Game</h2>
|
||
<p class="game-card-desc">
|
||
Erlebe Keuschheit auf eine neue Art: Kartenbasierte Locks, Keyholder-System,
|
||
Community-Abstimmungen und tägliche Verifizierungen machen jedes Lock einzigartig.
|
||
</p>
|
||
<a href="/games/chastity/neulock.html"><button class="game-card-btn">Neues Lock erstellen</button></a>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Profilbesucher -->
|
||
<div id="visitorsSection" style="display:none;">
|
||
<div class="section-label">Profilbesucher</div>
|
||
<div class="visitors-strip" id="visitorsStrip"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script src="/js/icons.js"></script>
|
||
<script src="/js/sidebar.js"></script>
|
||
<script>
|
||
fetch('/login/me')
|
||
.then(r => {
|
||
if (r.status === 401) { window.location.href = '/login.html'; return null; }
|
||
return r.json();
|
||
})
|
||
.then(user => {
|
||
if (user) {
|
||
document.getElementById('greeting').textContent = 'Willkommen zurück, ' + user.name + '!';
|
||
loadVisitors();
|
||
}
|
||
})
|
||
.catch(() => { window.location.href = '/login.html'; });
|
||
|
||
function relativeTime(isoString) {
|
||
const diff = Math.floor((Date.now() - new Date(isoString)) / 1000);
|
||
if (diff < 60) return 'gerade eben';
|
||
if (diff < 3600) return 'vor ' + Math.floor(diff / 60) + ' Min.';
|
||
if (diff < 86400) return 'vor ' + Math.floor(diff / 3600) + ' Std.';
|
||
return 'vor ' + Math.floor(diff / 86400) + ' Tag' + (Math.floor(diff / 86400) === 1 ? '' : 'en');
|
||
}
|
||
|
||
async function loadVisitors() {
|
||
try {
|
||
const res = await fetch('/social/profile-visits/my-visitors');
|
||
if (!res.ok) return;
|
||
const visitors = await res.json();
|
||
if (!visitors.length) return;
|
||
|
||
const strip = document.getElementById('visitorsStrip');
|
||
strip.innerHTML = visitors.map(v => `
|
||
<a class="visitor-card" href="/community/benutzer.html?userId=${v.userId}">
|
||
<div class="visitor-avatar">
|
||
${v.profilePicture
|
||
? `<img src="data:image/png;base64,${v.profilePicture}" alt="${v.name}">`
|
||
: '◉'}
|
||
</div>
|
||
<span class="visitor-name">${v.name}</span>
|
||
<span class="visitor-time">${relativeTime(v.visitedAt)}</span>
|
||
</a>
|
||
`).join('');
|
||
document.getElementById('visitorsSection').style.display = '';
|
||
} catch (_) {}
|
||
}
|
||
</script>
|
||
</body>
|
||
</html>
|