Aufgabenverwaltung angepasst, Eventseite weiter bearbeitet
Some checks failed
Host-Based Deploy (Java 21 Fix) / build-and-run (push) Has been cancelled
Some checks failed
Host-Based Deploy (Java 21 Fix) / build-and-run (push) Has been cancelled
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -120,7 +120,8 @@
|
||||
.gruppe-info { font-size:0.75rem; color:var(--color-muted); margin-top:0.2rem; }
|
||||
.gruppe-badges { display:flex; gap:0.3rem; margin-top:0.25rem; flex-wrap:wrap; }
|
||||
.gruppe-badge { font-size:0.65rem; padding:0.1rem 0.4rem; border-radius:20px; background:rgba(255,255,255,0.07); color:var(--color-muted); }
|
||||
.gruppe-badge-public { background:rgba(46,204,113,0.15); color:var(--color-success); }
|
||||
.gruppe-badge-public { background:rgba(46,204,113,0.15); color:var(--color-success); }
|
||||
.gruppe-badge-vanilla { background:#e8f5e9; color:#2e7d32; border:1px solid #a5d6a7; }
|
||||
.gruppe-toggle { font-size:0.75rem; color:var(--color-muted); flex-shrink:0; transition:transform 0.2s; }
|
||||
.gruppe-card.open .gruppe-toggle { transform:rotate(90deg); }
|
||||
.gruppe-body { border-top:1px solid var(--color-secondary); padding:1rem 1rem 0.75rem; }
|
||||
@@ -277,6 +278,12 @@
|
||||
<span style="font-size:0.78rem; color:var(--color-muted);">Aktuelles Bild – neues wählen zum Ersetzen</span>
|
||||
</div>
|
||||
<input type="file" id="gBild" accept="image/*">
|
||||
<label style="margin-top:0.5rem;">
|
||||
<span class="modal-check">
|
||||
<input type="checkbox" id="gVanilla">
|
||||
Auch für Vanilla-Game verfügbar
|
||||
</span>
|
||||
</label>
|
||||
<div class="modal-error" id="gruppeModalError"></div>
|
||||
<div class="modal-actions">
|
||||
<button class="btn-cancel" id="gruppeModalCancel">Abbrechen</button>
|
||||
@@ -986,7 +993,7 @@ function renderAdminGruppen(gruppen) {
|
||||
<div class="gruppe-meta">
|
||||
<div class="gruppe-name">${esc(g.name)}</div>
|
||||
<div class="gruppe-info">${g.von ? esc(g.von) + (counts ? ' · ' : '') : ''}${counts || 'Keine Einträge'}</div>
|
||||
<div class="gruppe-badges"><span class="gruppe-badge gruppe-badge-public">Öffentlich</span></div>
|
||||
<div class="gruppe-badges"><span class="gruppe-badge gruppe-badge-public">Öffentlich</span>${g.vanillaAvailable ? '<span class="gruppe-badge gruppe-badge-vanilla">Vanilla</span>' : ''}</div>
|
||||
</div>
|
||||
<span class="gruppe-toggle">▶</span>
|
||||
</div>
|
||||
@@ -1262,6 +1269,7 @@ function openGruppeModal(editId) {
|
||||
document.getElementById('gName').value = g.name || '';
|
||||
document.getElementById('gVon').value = g.von || '';
|
||||
document.getElementById('gDesc').value = g.beschreibung || '';
|
||||
document.getElementById('gVanilla').checked = g.vanillaAvailable || false;
|
||||
const imgWrap = document.getElementById('gCurrentImgWrap');
|
||||
if (g.bild) { document.getElementById('gCurrentImg').src = 'data:image/png;base64,' + g.bild; imgWrap.style.display = 'flex'; }
|
||||
else imgWrap.style.display = 'none';
|
||||
@@ -1270,6 +1278,7 @@ function openGruppeModal(editId) {
|
||||
document.getElementById('gName').value = '';
|
||||
document.getElementById('gVon').value = '';
|
||||
document.getElementById('gDesc').value = '';
|
||||
document.getElementById('gVanilla').checked = false;
|
||||
document.getElementById('gCurrentImgWrap').style.display = 'none';
|
||||
}
|
||||
gruppeModal.classList.add('open');
|
||||
@@ -1348,7 +1357,7 @@ gruppeModalSave.addEventListener('click', async () => {
|
||||
let bildBase64 = null;
|
||||
const fi = document.getElementById('gBild');
|
||||
if (fi.files.length > 0) bildBase64 = await toBase64(fi.files[0]);
|
||||
const payload = { name, von: document.getElementById('gVon').value.trim() || null, beschreibung: document.getElementById('gDesc').value.trim() || null, bild: bildBase64 };
|
||||
const payload = { name, von: document.getElementById('gVon').value.trim() || null, beschreibung: document.getElementById('gDesc').value.trim() || null, vanillaAvailable: document.getElementById('gVanilla').checked, bild: bildBase64 };
|
||||
const isEdit = currentEditGruppeId != null;
|
||||
fetch(isEdit ? `/admin/aufgabengruppen/${currentEditGruppeId}` : '/admin/aufgabengruppen', {
|
||||
method: isEdit ? 'PUT' : 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload)
|
||||
|
||||
@@ -195,6 +195,7 @@ function renderPage(evt) {
|
||||
|
||||
const totalAttendees = (evt.attendees || []).length;
|
||||
const attending = evt.attendingMe;
|
||||
const isPast = new Date(evt.startAt) < new Date();
|
||||
|
||||
document.getElementById('content').innerHTML = `
|
||||
<div class="evt-header">
|
||||
@@ -211,11 +212,13 @@ function renderPage(evt) {
|
||||
<button class="btn" style="background:#c0392b;font-size:0.85rem;" onclick="openDeleteConfirm()">Löschen</button>
|
||||
</div>` : ''}
|
||||
<div style="display:flex;align-items:center;gap:0.4rem;flex-wrap:wrap;">
|
||||
<button class="btn" id="attendBtn"
|
||||
style="${attending ? 'background:var(--color-secondary);color:var(--color-text);' : ''}"
|
||||
onclick="toggleAttend()">
|
||||
${attending ? '✓ Ich bin dabei' : '+ Ich bin dabei'}
|
||||
</button>
|
||||
${isPast
|
||||
? `<span style="color:var(--color-muted);font-size:0.85rem;">Veranstaltung bereits beendet</span>`
|
||||
: `<button class="btn" id="attendBtn"
|
||||
style="${attending ? 'background:var(--color-secondary);color:var(--color-text);' : ''}"
|
||||
onclick="toggleAttend()">
|
||||
${attending ? '✓ Ich bin dabei' : '+ Ich bin dabei'}
|
||||
</button>`}
|
||||
<span style="color:var(--color-muted);font-size:0.85rem;" id="attendCount">${totalAttendees} Teilnehmer*in(nen)</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -445,6 +445,9 @@ function renderPage() {
|
||||
${isOwner ? `<button class="btn" style="font-size:0.8rem;" onclick="openEventModal()">+ Veranstaltung erstellen</button>` : ''}
|
||||
</div>
|
||||
<div class="event-list" id="eventList"><p style="color:var(--color-muted);font-size:0.9rem;">Wird geladen…</p></div>
|
||||
<div id="allEventsLinkWrap" style="display:none;margin-top:0.75rem;">
|
||||
<a id="allEventsLink" href="#" class="btn" style="display:inline-block;font-size:0.85rem;background:var(--color-secondary);color:var(--color-text);text-decoration:none;padding:0.45rem 1rem;border-radius:6px;">Alle Events anzeigen →</a>
|
||||
</div>
|
||||
<div id="pastEventsSection" style="display:none;">
|
||||
<div class="section-title" style="margin-top:1.5rem;">Vergangene Veranstaltungen</div>
|
||||
<div class="event-list" id="pastEventList"></div>
|
||||
@@ -517,8 +520,8 @@ function renderPage() {
|
||||
${locHeaderHtml}
|
||||
${hoursHtml}
|
||||
${gallerySection}
|
||||
${feedSection}
|
||||
${eventsSection}`;
|
||||
${eventsSection}
|
||||
${feedSection}`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -587,15 +590,27 @@ async function loadEvents() {
|
||||
if (!list) return;
|
||||
|
||||
const now = new Date();
|
||||
const future = events.filter(e => new Date(e.startAt) >= now);
|
||||
const future = events.filter(e => new Date(e.startAt) >= now)
|
||||
.sort((a, b) => new Date(a.startAt) - new Date(b.startAt));
|
||||
const past = events.filter(e => new Date(e.startAt) < now)
|
||||
.slice(-5) // letzte 5
|
||||
.slice(-3) // letzte 3
|
||||
.reverse(); // neueste zuerst
|
||||
|
||||
list.innerHTML = future.length
|
||||
? future.map(e => buildEventCard(e, false)).join('')
|
||||
const preview = future.slice(0, 3);
|
||||
list.innerHTML = preview.length
|
||||
? preview.map(e => buildEventCard(e, false)).join('')
|
||||
: '<p style="color:var(--color-muted);font-size:0.9rem;">Keine bevorstehenden Veranstaltungen.</p>';
|
||||
|
||||
const linkWrap = document.getElementById('allEventsLinkWrap');
|
||||
if (linkWrap) {
|
||||
if (future.length > 3) {
|
||||
document.getElementById('allEventsLink').href = `/community/location-events.html?id=${locationId}`;
|
||||
linkWrap.style.display = '';
|
||||
} else {
|
||||
linkWrap.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
const pastSection = document.getElementById('pastEventsSection');
|
||||
if (past.length && pastSection) {
|
||||
document.getElementById('pastEventList').innerHTML = past.map(e => buildEventCard(e, true)).join('');
|
||||
@@ -1358,11 +1373,15 @@ function renderLocPost(p) {
|
||||
<button class="post-action-btn post-delete" onclick="event.stopPropagation();deleteLocPost('${p.postId}')" title="Löschen">🗑</button>
|
||||
</div>` : '';
|
||||
|
||||
const authorUrl = p.posterType === 'LOCATION'
|
||||
? `/community/location-detail.html?id=${p.locationId || p.authorId}`
|
||||
: `/community/benutzer.html?userId=${p.authorId}`;
|
||||
|
||||
return `<div class="post-card${clickableClass}" id="lp-${p.postId}"${onClickAttr}>
|
||||
<div class="post-header">
|
||||
<div class="post-avatar">${avHtml}</div>
|
||||
<div class="post-avatar"><a href="${authorUrl}" onclick="event.stopPropagation()" style="display:contents;">${avHtml}</a></div>
|
||||
<div>
|
||||
<div class="post-author">${escHtml(p.authorName || p.locationName || '')}</div>
|
||||
<div class="post-author"><a href="${authorUrl}" style="color:inherit;text-decoration:none;" onclick="event.stopPropagation()">${escHtml(p.authorName || p.locationName || '')}</a></div>
|
||||
<div class="post-meta">${dateStr}${editedHtml}</div>
|
||||
</div>
|
||||
${adminBtns}
|
||||
@@ -1401,11 +1420,15 @@ function openLpLb(postId) {
|
||||
+ ' ' + new Date(p.createdAt).toLocaleTimeString('de-DE', { hour:'2-digit', minute:'2-digit' });
|
||||
const editedHtml = p.editedAt ? ' <span style="font-size:0.7rem;color:var(--color-muted);">(bearbeitet)</span>' : '';
|
||||
|
||||
const lbAuthorUrl = p.posterType === 'LOCATION'
|
||||
? `/community/location-detail.html?id=${p.locationId || p.authorId}`
|
||||
: `/community/benutzer.html?userId=${p.authorId}`;
|
||||
|
||||
document.getElementById('lbPostBody').innerHTML = `
|
||||
<div class="post-header">
|
||||
<div class="post-avatar">${avHtml}</div>
|
||||
<div class="post-avatar"><a href="${lbAuthorUrl}" style="display:contents;">${avHtml}</a></div>
|
||||
<div>
|
||||
<div class="post-author">${escHtml(p.authorName || p.locationName || '')}</div>
|
||||
<div class="post-author"><a href="${lbAuthorUrl}" style="color:inherit;text-decoration:none;">${escHtml(p.authorName || p.locationName || '')}</a></div>
|
||||
<div class="post-meta">${dateStr}${editedHtml}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
164
bin/main/static/community/location-events.html
Normal file
164
bin/main/static/community/location-events.html
Normal file
@@ -0,0 +1,164 @@
|
||||
<!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>Alle Events – xXx Sphere</title>
|
||||
<link rel="stylesheet" href="/css/variables.css">
|
||||
<link rel="stylesheet" href="/css/style.css">
|
||||
<link rel="stylesheet" href="/css/community.css">
|
||||
<style>
|
||||
.back-link { display:inline-flex; align-items:center; gap:0.35rem; color:var(--color-muted); font-size:0.88rem; text-decoration:none; margin-bottom:1rem; }
|
||||
.back-link:hover { color:var(--color-primary); }
|
||||
|
||||
.page-title { font-size:1.15rem; font-weight:700; margin:0 0 1.25rem; }
|
||||
|
||||
.event-list { display:flex; flex-direction:column; gap:0.75rem; }
|
||||
.event-card { background:var(--color-card); border:1px solid var(--color-secondary); border-radius:10px; display:flex; gap:0.75rem; padding:0.75rem; text-decoration:none; color:inherit; transition:border-color 0.15s; cursor:pointer; }
|
||||
.event-card:hover { border-color:var(--color-primary); }
|
||||
.event-card-img { width:64px; height:64px; border-radius:8px; object-fit:cover; background:var(--color-secondary); flex-shrink:0; overflow:hidden; display:flex; align-items:center; justify-content:center; font-size:1.4rem; }
|
||||
.event-card-img img { width:100%; height:100%; object-fit:cover; }
|
||||
.event-card-body { flex:1; min-width:0; }
|
||||
.event-card-title { font-weight:600; font-size:0.92rem; margin:0 0 0.2rem; }
|
||||
.event-card-date { font-size:0.78rem; color:var(--color-muted); }
|
||||
.event-card-attendees { font-size:0.78rem; color:var(--color-muted); }
|
||||
|
||||
.paging-bar { display:flex; align-items:center; justify-content:center; gap:0.75rem; margin-top:1.25rem; flex-wrap:wrap; }
|
||||
.paging-bar button { background:var(--color-secondary); border:none; color:var(--color-text); padding:0.45rem 1rem; border-radius:6px; font-size:0.88rem; cursor:pointer; transition:background 0.15s; }
|
||||
.paging-bar button:hover:not(:disabled) { background:var(--color-primary); color:#fff; }
|
||||
.paging-bar button:disabled { opacity:0.4; cursor:default; }
|
||||
.paging-info { font-size:0.85rem; color:var(--color-muted); }
|
||||
|
||||
.empty-hint { color:var(--color-muted); font-size:0.9rem; }
|
||||
</style>
|
||||
</head>
|
||||
<body class="app">
|
||||
|
||||
<div class="main">
|
||||
<div class="content">
|
||||
|
||||
<a class="back-link" id="backLink" href="#">‹ Zurück zur Location</a>
|
||||
|
||||
<div id="locName" class="page-title">Alle Events</div>
|
||||
|
||||
<div id="eventList" class="event-list">
|
||||
<p class="empty-hint">Wird geladen…</p>
|
||||
</div>
|
||||
|
||||
<div class="paging-bar" id="pagingBar" style="display:none;">
|
||||
<button id="prevBtn" onclick="changePage(-1)" disabled>‹ Zurück</button>
|
||||
<span class="paging-info" id="pagingInfo"></span>
|
||||
<button id="nextBtn" onclick="changePage(1)">Weiter ›</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/js/nav.js"></script>
|
||||
<script>
|
||||
const PAGE_SIZE = 10;
|
||||
const params = new URLSearchParams(location.search);
|
||||
const locationId = params.get('id');
|
||||
|
||||
let allEvents = [];
|
||||
let currentPage = 0;
|
||||
|
||||
document.getElementById('backLink').href = `/community/location-detail.html?id=${locationId}`;
|
||||
|
||||
function escHtml(s) {
|
||||
if (!s) return '';
|
||||
return s.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"');
|
||||
}
|
||||
|
||||
function formatDate(iso) {
|
||||
if (!iso) return '';
|
||||
const d = new Date(iso);
|
||||
return d.toLocaleDateString('de-DE', { weekday:'short', day:'2-digit', month:'2-digit', year:'numeric' })
|
||||
+ ' ' + d.toLocaleTimeString('de-DE', { hour:'2-digit', minute:'2-digit' }) + ' Uhr';
|
||||
}
|
||||
|
||||
function buildEventCard(e) {
|
||||
const imgHtml = e.imageData
|
||||
? `<img src="data:image/jpeg;base64,${e.imageData}" alt="${escHtml(e.title)}">`
|
||||
: '🗓';
|
||||
return `
|
||||
<a class="event-card" href="/community/event-detail.html?id=${e.eventId}">
|
||||
<div class="event-card-img">${imgHtml}</div>
|
||||
<div class="event-card-body">
|
||||
<div class="event-card-title">${escHtml(e.title)}</div>
|
||||
<div class="event-card-date">${formatDate(e.startAt)}</div>
|
||||
<div class="event-card-attendees">${e.attendeeCount} Teilnehmer*in(nen)${e.attendingMe ? ' · Du nimmst teil' : ''}</div>
|
||||
</div>
|
||||
</a>`;
|
||||
}
|
||||
|
||||
function renderPage() {
|
||||
const list = document.getElementById('eventList');
|
||||
const totalPages = Math.ceil(allEvents.length / PAGE_SIZE);
|
||||
const start = currentPage * PAGE_SIZE;
|
||||
const slice = allEvents.slice(start, start + PAGE_SIZE);
|
||||
|
||||
list.innerHTML = slice.length
|
||||
? slice.map(buildEventCard).join('')
|
||||
: '<p class="empty-hint">Keine weiteren Veranstaltungen.</p>';
|
||||
|
||||
const pagingBar = document.getElementById('pagingBar');
|
||||
if (allEvents.length > PAGE_SIZE) {
|
||||
pagingBar.style.display = '';
|
||||
document.getElementById('prevBtn').disabled = currentPage === 0;
|
||||
document.getElementById('nextBtn').disabled = currentPage >= totalPages - 1;
|
||||
document.getElementById('pagingInfo').textContent =
|
||||
`Seite ${currentPage + 1} von ${totalPages} (${allEvents.length} Events)`;
|
||||
} else {
|
||||
pagingBar.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
function changePage(dir) {
|
||||
const totalPages = Math.ceil(allEvents.length / PAGE_SIZE);
|
||||
const next = currentPage + dir;
|
||||
if (next < 0 || next >= totalPages) return;
|
||||
currentPage = next;
|
||||
renderPage();
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
}
|
||||
|
||||
async function init() {
|
||||
if (!locationId) {
|
||||
document.getElementById('eventList').innerHTML = '<p class="empty-hint">Keine Location-ID angegeben.</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
// Locationname laden
|
||||
const locRes = await fetch(`/locations/${locationId}`);
|
||||
if (locRes.ok) {
|
||||
const loc = await locRes.json();
|
||||
document.getElementById('locName').textContent = `Alle Events – ${loc.name}`;
|
||||
document.title = `Events – ${loc.name} – xXx Sphere`;
|
||||
}
|
||||
|
||||
// Events laden
|
||||
const res = await fetch(`/locations/${locationId}/events`);
|
||||
if (!res.ok) {
|
||||
document.getElementById('eventList').innerHTML = '<p class="empty-hint">Events konnten nicht geladen werden.</p>';
|
||||
return;
|
||||
}
|
||||
const events = await res.json();
|
||||
const now = new Date();
|
||||
allEvents = events
|
||||
.filter(e => new Date(e.startAt) >= now)
|
||||
.sort((a, b) => new Date(a.startAt) - new Date(b.startAt));
|
||||
|
||||
if (allEvents.length === 0) {
|
||||
document.getElementById('eventList').innerHTML = '<p class="empty-hint">Keine bevorstehenden Veranstaltungen.</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
renderPage();
|
||||
}
|
||||
|
||||
init();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -95,6 +95,7 @@
|
||||
}
|
||||
.gruppe-badge-private { background: rgba(233,69,96,0.15); color: var(--color-primary); }
|
||||
.gruppe-badge-public { background: rgba(46,204,113,0.15); color: var(--color-success); }
|
||||
.gruppe-badge-vanilla { background: #e8f5e9; color: #2e7d32; border: 1px solid #a5d6a7; }
|
||||
.gruppe-toggle { font-size: 0.75rem; color: var(--color-muted); flex-shrink: 0; transition: transform 0.2s; }
|
||||
.gruppe-card.open .gruppe-toggle { transform: rotate(90deg); }
|
||||
|
||||
@@ -367,6 +368,12 @@
|
||||
Gruppe veröffentlichen (für alle sichtbar)
|
||||
</span>
|
||||
</label>
|
||||
<label>
|
||||
<span class="modal-check">
|
||||
<input type="checkbox" id="gVanilla">
|
||||
Auch für Vanilla-Game verfügbar
|
||||
</span>
|
||||
</label>
|
||||
<div class="modal-error" id="modalError"></div>
|
||||
<div class="modal-actions">
|
||||
<button class="btn-cancel" id="cancelBtn">Abbrechen</button>
|
||||
@@ -715,6 +722,7 @@
|
||||
if (g.privateGruppe) badges.push(`<span class="gruppe-badge gruppe-badge-private">Privat</span>`);
|
||||
else badges.push(`<span class="gruppe-badge gruppe-badge-public">Öffentlich</span>`);
|
||||
if (type === 'user' && g.subscriberCount > 0) badges.push(`<span class="gruppe-badge">♥ ${g.subscriberCount} Abo${g.subscriberCount !== 1 ? 's' : ''}</span>`);
|
||||
if (g.vanillaAvailable) badges.push(`<span class="gruppe-badge gruppe-badge-vanilla">Vanilla</span>`);
|
||||
|
||||
return `
|
||||
<div class="gruppe-card" id="gruppe-${esc(g.gruppenId)}">
|
||||
@@ -1069,6 +1077,7 @@
|
||||
pubCb.checked = !g.privateGruppe;
|
||||
pubCb.disabled = g.privateGruppe; // Veröffentlichen nur über den Veröffentlichen-Button
|
||||
document.getElementById('gPublicLabel').style.display = 'block';
|
||||
document.getElementById('gVanilla').checked = g.vanillaAvailable || false;
|
||||
const imgWrap = document.getElementById('gCurrentImgWrap');
|
||||
if (g.bild) {
|
||||
document.getElementById('gCurrentImg').src = 'data:image/png;base64,' + g.bild;
|
||||
@@ -1086,6 +1095,7 @@
|
||||
document.getElementById('gDesc').value = '';
|
||||
document.getElementById('gPublic').checked = false;
|
||||
document.getElementById('gPublicLabel').style.display = 'none';
|
||||
document.getElementById('gVanilla').checked = false;
|
||||
document.getElementById('gCurrentImgWrap').style.display = 'none';
|
||||
gruppeModal.classList.add('open');
|
||||
document.getElementById('gName').focus();
|
||||
@@ -1119,6 +1129,7 @@
|
||||
name,
|
||||
beschreibung: document.getElementById('gDesc').value.trim() || null,
|
||||
privateGruppe: isEdit ? !document.getElementById('gPublic').checked : true,
|
||||
vanillaAvailable: document.getElementById('gVanilla').checked,
|
||||
bild: bildBase64
|
||||
};
|
||||
|
||||
|
||||
@@ -97,6 +97,7 @@
|
||||
.item-img { width: 38px; height: 38px; object-fit: cover; border-radius: 6px; flex-shrink: 0; }
|
||||
.gruppe-item-name, .toy-item-name { font-size: 0.95rem; font-weight: 600; color: var(--color-text); }
|
||||
.gruppe-item-desc, .toy-item-desc { display: block; font-size: 0.8rem; color: var(--color-muted); margin-top: 0.15rem; }
|
||||
.vanilla-badge { display: inline-block; font-size: 0.65rem; font-weight: 700; padding: 0.1rem 0.35rem; border-radius: 3px; background: #e8f5e9; color: #2e7d32; border: 1px solid #a5d6a7; margin-left: 0.35rem; vertical-align: middle; letter-spacing: 0.03em; }
|
||||
.empty-hint { color: var(--color-muted); font-size: 0.875rem; font-style: italic; padding: 0.5rem 0; }
|
||||
.aufgaben-section-label { font-size: 0.78rem; font-weight: 600; color: var(--color-muted); text-transform: uppercase; letter-spacing: 0.04em; margin: 1rem 0 0.5rem 0; }
|
||||
.aufgaben-section-label:first-child { margin-top: 0; }
|
||||
@@ -653,9 +654,10 @@
|
||||
}
|
||||
ul.innerHTML = gruppen.map(g => {
|
||||
const checked = savedGruppen.has(g.gruppenId);
|
||||
const vanillaBadge = g.vanillaAvailable ? '<span class="vanilla-badge">Vanilla</span>' : '';
|
||||
return `<li><label class="gruppe-item${checked ? ' is-checked' : ''}">
|
||||
<input type="checkbox" value="${g.gruppenId}"${checked ? ' checked' : ''}>
|
||||
<span><span class="gruppe-item-name">${g.name}</span>${g.beschreibung ? `<span class="gruppe-item-desc">${g.beschreibung}</span>` : ''}</span>
|
||||
<span><span class="gruppe-item-name">${g.name}${vanillaBadge}</span>${g.beschreibung ? `<span class="gruppe-item-desc">${g.beschreibung}</span>` : ''}</span>
|
||||
${g.bild ? `<img class="item-img" src="data:image/png;base64,${g.bild}" alt="">` : ''}
|
||||
</label></li>`;
|
||||
}).join('');
|
||||
|
||||
@@ -887,11 +887,14 @@
|
||||
</div>`
|
||||
: '';
|
||||
const gruppeIdAttr = p.gruppeId ? ` data-gruppe-id="${p.gruppeId}"` : '';
|
||||
const authorUrl = p.posterType === 'LOCATION'
|
||||
? `/community/location-detail.html?id=${p.locationId || p.authorId}`
|
||||
: `/community/benutzer.html?userId=${p.authorId}`;
|
||||
return `<div class="post-card" id="hpc-${p.postId}"${gruppeIdAttr} onclick="homeOpenPost('${p.postId}')">
|
||||
<div class="post-header">
|
||||
<div class="post-avatar">${avatarHtml}</div>
|
||||
<div class="post-avatar"><a href="${authorUrl}" onclick="event.stopPropagation()" style="display:contents;">${avatarHtml}</a></div>
|
||||
<div>
|
||||
<div class="post-author">${esc(p.authorName)}${privacyLabel}</div>
|
||||
<div class="post-author"><a href="${authorUrl}" style="color:inherit;text-decoration:none;" onclick="event.stopPropagation()">${esc(p.authorName)}</a>${privacyLabel}</div>
|
||||
<div class="post-meta" id="hpm-${p.postId}">${fmtDate(p.createdAt)}${editedLabel}${groupBadge}</div>
|
||||
</div>
|
||||
${ownBtns}
|
||||
|
||||
Reference in New Issue
Block a user