BDSM Game umgesetzt, Community Features ergänzt
This commit is contained in:
@@ -7,70 +7,6 @@
|
||||
<link rel="stylesheet" href="/css/variables.css">
|
||||
<link rel="stylesheet" href="/css/style.css">
|
||||
<style>
|
||||
body { display: block; min-height: 100vh; }
|
||||
.layout { display: flex; min-height: 100vh; }
|
||||
|
||||
/* ── Sidebar ── */
|
||||
.sidebar {
|
||||
width: 240px; background: var(--color-card);
|
||||
border-right: 1px solid var(--color-secondary);
|
||||
display: flex; flex-direction: column;
|
||||
position: fixed; top: 0; left: 0;
|
||||
height: 100vh; overflow-y: auto;
|
||||
z-index: 100; transition: transform 0.25s ease;
|
||||
}
|
||||
.sidebar-brand {
|
||||
color: var(--color-primary); font-size: 1.1rem; font-weight: 700;
|
||||
padding: 1.25rem 1.25rem 1rem;
|
||||
border-bottom: 1px solid var(--color-secondary); flex-shrink: 0;
|
||||
}
|
||||
.sidebar ul { list-style: none; padding: 0.5rem 0; }
|
||||
.sidebar ul li a {
|
||||
display: flex; align-items: center; gap: 0.75rem;
|
||||
padding: 0.7rem 1.25rem; color: var(--color-text);
|
||||
text-decoration: none; font-size: 0.95rem;
|
||||
border-left: 3px solid transparent;
|
||||
transition: background 0.15s, color 0.15s, border-color 0.15s;
|
||||
}
|
||||
.sidebar ul li a:hover, .sidebar ul li a.active {
|
||||
background: var(--color-secondary); color: var(--color-primary);
|
||||
border-left-color: var(--color-primary);
|
||||
}
|
||||
.sidebar ul li a .icon { font-size: 1rem; width: 1.2rem; text-align: center; flex-shrink: 0; }
|
||||
|
||||
/* ── Main ── */
|
||||
.main { margin-left: 240px; flex: 1; display: flex; flex-direction: column; min-height: 100vh; }
|
||||
|
||||
/* ── Topbar ── */
|
||||
.topbar {
|
||||
display: flex; align-items: center; gap: 1rem;
|
||||
padding: 0.9rem 1.5rem; background: var(--color-card);
|
||||
border-bottom: 1px solid var(--color-secondary);
|
||||
position: sticky; top: 0; z-index: 50;
|
||||
}
|
||||
.topbar h1 { font-size: 1.2rem; font-weight: 600; }
|
||||
.burger {
|
||||
display: none; background: none; border: none; cursor: pointer;
|
||||
color: var(--color-text); padding: 0.25rem 0.4rem;
|
||||
border-radius: 4px; transition: background 0.15s; flex-shrink: 0;
|
||||
}
|
||||
.burger:hover { background: var(--color-secondary); }
|
||||
.burger-icon { display: flex; flex-direction: column; gap: 5px; width: 22px; }
|
||||
.burger-icon span {
|
||||
display: block; height: 2px; background: var(--color-text);
|
||||
border-radius: 2px; transition: transform 0.25s, opacity 0.25s;
|
||||
}
|
||||
.burger.open .burger-icon span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
|
||||
.burger.open .burger-icon span:nth-child(2) { opacity: 0; }
|
||||
.burger.open .burger-icon span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
|
||||
|
||||
.content { padding: 2rem 1.5rem; flex: 1; }
|
||||
|
||||
.overlay {
|
||||
display: none; position: fixed; inset: 0;
|
||||
background: rgba(0,0,0,0.55); z-index: 90;
|
||||
}
|
||||
|
||||
/* ── Section ── */
|
||||
.section + .section { margin-top: 2.5rem; }
|
||||
.section-header {
|
||||
@@ -272,6 +208,25 @@
|
||||
.modal-actions .btn-save:disabled { opacity: 0.5; cursor: default; }
|
||||
.modal-error { color: var(--color-primary); font-size: 0.82rem; margin-top: 0.75rem; display: none; }
|
||||
|
||||
/* ── Placeholder-Hint ── */
|
||||
.label-with-hint { display: flex; align-items: center; gap: 0.4rem; }
|
||||
.btn-hint {
|
||||
background: none; border: 1px solid rgba(136,136,136,0.4); border-radius: 50%;
|
||||
color: var(--color-muted); font-size: 0.7rem; font-style: italic; font-weight: 700;
|
||||
width: 16px; height: 16px; line-height: 1; padding: 0;
|
||||
cursor: pointer; flex-shrink: 0; transition: border-color 0.15s, color 0.15s;
|
||||
}
|
||||
.btn-hint:hover { border-color: var(--color-primary); color: var(--color-primary); }
|
||||
.placeholder-hint {
|
||||
background: rgba(255,255,255,0.04); border: 1px solid rgba(136,136,136,0.25);
|
||||
border-radius: 6px; padding: 0.5rem 0.7rem; margin-bottom: 0.3rem;
|
||||
font-size: 0.78rem; color: var(--color-muted); line-height: 1.6;
|
||||
}
|
||||
.placeholder-hint code {
|
||||
background: rgba(233,69,96,0.12); color: var(--color-primary);
|
||||
border-radius: 3px; padding: 0.05rem 0.3rem; font-size: 0.75rem;
|
||||
}
|
||||
|
||||
/* ── Item-Add-Modal extra ── */
|
||||
.modal-two-col { display: flex; gap: 0.75rem; }
|
||||
.modal-two-col > * { flex: 1; }
|
||||
@@ -326,8 +281,7 @@
|
||||
}
|
||||
.btn-toy-add:hover { border-color: var(--color-primary); color: var(--color-primary); }
|
||||
|
||||
/* ── Toy-Suchmodal ── */
|
||||
#toySearchModal .modal-box { max-width: 420px; }
|
||||
/* ── Toy-Suche (inline) ── */
|
||||
.toy-search-input {
|
||||
width: 100%; box-sizing: border-box; padding: 0.45rem 0.7rem;
|
||||
background: var(--color-secondary); border: 1px solid rgba(136,136,136,0.3);
|
||||
@@ -368,19 +322,9 @@
|
||||
flex-shrink: 0; margin-top: 0.15rem;
|
||||
}
|
||||
|
||||
/* ── Mobile ── */
|
||||
@media (max-width: 768px) {
|
||||
.sidebar { transform: translateX(-100%); }
|
||||
.sidebar.open { transform: translateX(0); box-shadow: 4px 0 20px rgba(0,0,0,0.5); }
|
||||
.main { margin-left: 0; }
|
||||
.burger { display: flex; }
|
||||
.overlay.visible { display: block; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="overlay" id="overlay"></div>
|
||||
<body class="app">
|
||||
|
||||
<!-- Gruppe-Modal -->
|
||||
<div class="modal-backdrop" id="gruppeModal">
|
||||
@@ -439,9 +383,38 @@
|
||||
<label for="iKurzText">Kurzbezeichnung *</label>
|
||||
<input type="text" id="iKurzText" maxlength="200" placeholder="Kurzer Name">
|
||||
|
||||
<label for="iText">Beschreibung *</label>
|
||||
<label class="label-with-hint">
|
||||
<span>Beschreibung *</span>
|
||||
<button type="button" class="btn-hint" onclick="togglePlaceholderHint()" title="Platzhalter-Hilfe">i</button>
|
||||
</label>
|
||||
<div id="iPlaceholderHint" style="display:none;">
|
||||
<div class="placeholder-hint">
|
||||
In Texten können Platzhalter verwendet werden:<br>
|
||||
<code>{AKTIV}</code> – Name des aktiven Parts<br>
|
||||
<code>{PASSIV}</code> – Name des passiven Parts
|
||||
</div>
|
||||
</div>
|
||||
<textarea id="iText" rows="4" maxlength="4000" placeholder="Ausführliche Beschreibung…"></textarea>
|
||||
|
||||
<!-- Finisher: Geschlecht -->
|
||||
<div id="iGeschlechtRow">
|
||||
<label>Geschlecht der Person die kommt *</label>
|
||||
<div style="display:flex; gap:1.5rem; margin-top:0.5rem;" id="iGeschlecht">
|
||||
<label style="display:flex; align-items:center; gap:0.4rem; font-size:0.85rem; cursor:pointer;">
|
||||
<input type="radio" name="iGeschlechtRadio" value="WEIBLICH" style="accent-color:var(--color-primary);">
|
||||
Weiblich
|
||||
</label>
|
||||
<label style="display:flex; align-items:center; gap:0.4rem; font-size:0.85rem; cursor:pointer;">
|
||||
<input type="radio" name="iGeschlechtRadio" value="DIVERS" style="accent-color:var(--color-primary);">
|
||||
Divers
|
||||
</label>
|
||||
<label style="display:flex; align-items:center; gap:0.4rem; font-size:0.85rem; cursor:pointer;">
|
||||
<input type="radio" name="iGeschlechtRadio" value="MAENNLICH" style="accent-color:var(--color-primary);">
|
||||
Männlich
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Aufgabe / Strafe: Level + Sekunden -->
|
||||
<div id="iLevelRow">
|
||||
<label for="iLevel">Level *</label>
|
||||
@@ -481,6 +454,27 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Finisher: Werkzeuge (eigene Labels, kein Umschnalldildo bei aktiv) -->
|
||||
<div id="iWerkzeugFinisherAktivRow">
|
||||
<label>Benötigt (Person die kommt)</label>
|
||||
<div class="werkzeug-checks" id="iWerkzeugFinisherAktiv">
|
||||
<label class="werkzeug-check"><span>Mund</span><input type="checkbox" value="MUND"></label>
|
||||
<label class="werkzeug-check"><span>Vagina</span><input type="checkbox" value="VAGINA"></label>
|
||||
<label class="werkzeug-check"><span>Penis</span><input type="checkbox" value="PENIS"></label>
|
||||
<label class="werkzeug-check"><span>Anus</span><input type="checkbox" value="ANUS"></label>
|
||||
</div>
|
||||
</div>
|
||||
<div id="iWerkzeugFinisherPassivRow">
|
||||
<label>Benötigt (Person die zum Kommen bringt)</label>
|
||||
<div class="werkzeug-checks" id="iWerkzeugFinisherPassiv">
|
||||
<label class="werkzeug-check"><span>Mund</span><input type="checkbox" value="MUND"></label>
|
||||
<label class="werkzeug-check"><span>Vagina</span><input type="checkbox" value="VAGINA"></label>
|
||||
<label class="werkzeug-check"><span>Penis</span><input type="checkbox" value="PENIS"></label>
|
||||
<label class="werkzeug-check"><span>Anus</span><input type="checkbox" value="ANUS"></label>
|
||||
<label class="werkzeug-check"><span>Umschnall-Dildo</span><input type="checkbox" value="UMSCHNALLDILDO"></label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Zeitstrafe: Minuten + SperreFuer + releaseText -->
|
||||
<div id="iMinutenRow">
|
||||
<label>Dauer (Minuten) *</label>
|
||||
@@ -513,6 +507,11 @@
|
||||
<label>Benötigte Toys (optional)</label>
|
||||
<div class="selected-toys-row" id="iSelectedToys"></div>
|
||||
<button class="btn-toy-add" type="button" id="iToyAddBtn">+ Toy hinzufügen</button>
|
||||
<div id="iToySearchArea" style="display:none; margin-top:0.5rem;">
|
||||
<input class="toy-search-input" type="text" id="toySearchInput" placeholder="Name filtern…" autocomplete="off">
|
||||
<div class="toy-search-results" id="toySearchResults"></div>
|
||||
<div id="toySearchEmpty" style="font-size:0.82rem; color:var(--color-muted); display:none; margin-top:0.4rem;">Keine Toys gefunden.</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-error" id="itemModalError"></div>
|
||||
<div class="modal-actions">
|
||||
@@ -522,46 +521,9 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── Toy-Suchmodal ── -->
|
||||
<div class="modal-overlay" id="toySearchModal">
|
||||
<div class="modal-box" style="max-width:420px;">
|
||||
<h2 class="modal-title">Toy auswählen</h2>
|
||||
<input class="toy-search-input" type="text" id="toySearchInput" placeholder="Name filtern…" autocomplete="off">
|
||||
<div class="toy-search-results" id="toySearchResults"></div>
|
||||
<div id="toySearchEmpty" style="font-size:0.82rem; color:var(--color-muted); display:none; margin-top:0.5rem;">Keine Toys gefunden.</div>
|
||||
<div class="modal-actions" style="margin-top:1rem;">
|
||||
<button class="btn-save" id="toySearchDoneBtn">Fertig</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layout">
|
||||
<aside class="sidebar" id="sidebar">
|
||||
<div class="sidebar-brand">XXX The Game</div>
|
||||
<ul>
|
||||
<li><a href="/userhome.html"><span class="icon">⊞</span> Dashboard</a></li>
|
||||
<li><a href="#"><span class="icon">▶</span> Meine Session</a></li>
|
||||
<li><a href="/aufgaben.html" class="active"><span class="icon">✓</span> Aufgaben</a></li>
|
||||
<li><a href="/entdecken.html"><span class="icon">⊙</span> Entdecken</a></li>
|
||||
<li><a href="#"><span class="icon">⚡</span> Strafen</a></li>
|
||||
<li><a href="/toys.html"><span class="icon">◈</span> Toys</a></li>
|
||||
<li><a href="#"><span class="icon">♥</span> Favoriten</a></li>
|
||||
<li><a href="#"><span class="icon">☰</span> Rangliste</a></li>
|
||||
<li><a href="#"><span class="icon">✉</span> Nachrichten</a></li>
|
||||
<li><a href="#"><span class="icon">⚙</span> Einstellungen</a></li>
|
||||
<li><a href="#" id="logoutLink"><span class="icon">⏏</span> Abmelden</a></li>
|
||||
</ul>
|
||||
</aside>
|
||||
|
||||
<div class="main">
|
||||
<header class="topbar">
|
||||
<button class="burger" id="burgerBtn" aria-label="Menü öffnen">
|
||||
<span class="burger-icon"><span></span><span></span><span></span></span>
|
||||
</button>
|
||||
<h1>Aufgaben</h1>
|
||||
</header>
|
||||
|
||||
<div class="content">
|
||||
<div class="main">
|
||||
<div class="content">
|
||||
|
||||
<!-- Meine Aufgabengruppen -->
|
||||
<div class="section">
|
||||
@@ -621,7 +583,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -708,13 +669,15 @@
|
||||
}
|
||||
list.innerHTML = gruppen.map(g => {
|
||||
_gruppeData[g.gruppenId] = g;
|
||||
const aufgabenCount = (g.aufgaben || []).length;
|
||||
const strafeCount = (g.strafen || []).length;
|
||||
const sperreCount = (g.sperren || []).length;
|
||||
const aufgabenCount = (g.aufgaben || []).length;
|
||||
const strafeCount = (g.strafen || []).length;
|
||||
const sperreCount = (g.sperren || []).length;
|
||||
const finisherCount = (g.finisher || []).length;
|
||||
const counts = [
|
||||
aufgabenCount ? `${aufgabenCount} Aufgabe${aufgabenCount !== 1 ? 'n' : ''}` : '',
|
||||
strafeCount ? `${strafeCount} Strafe${strafeCount !== 1 ? 'n' : ''}` : '',
|
||||
sperreCount ? `${sperreCount} Zeitstrafe${sperreCount !== 1 ? 'n' : ''}` : ''
|
||||
aufgabenCount ? `${aufgabenCount} Aufgabe${aufgabenCount !== 1 ? 'n' : ''}` : '',
|
||||
strafeCount ? `${strafeCount} Strafe${strafeCount !== 1 ? 'n' : ''}` : '',
|
||||
sperreCount ? `${sperreCount} Zeitstrafe${sperreCount !== 1 ? 'n' : ''}` : '',
|
||||
finisherCount ? `${finisherCount} Finisher` : ''
|
||||
].filter(Boolean).join(' · ');
|
||||
|
||||
const badges = [];
|
||||
@@ -738,9 +701,10 @@
|
||||
</div>
|
||||
<div class="gruppe-body" id="body-${esc(g.gruppenId)}" style="display:none;">
|
||||
${g.beschreibung ? `<div class="gruppe-desc">${esc(g.beschreibung)}</div>` : ''}
|
||||
${renderSubSection('Aufgaben', sortByLevelThenName(g.aufgaben || []), 'aufgabe', renderAufgabe, g.gruppenId, type)}
|
||||
${renderSubSection('Strafen', sortByLevelThenName(g.strafen || []), 'strafe', renderStrafe, g.gruppenId, type)}
|
||||
${renderSubSection('Zeitstrafen',sortByName(g.sperren || []), 'zeitstrafe',renderZeitstrafe, g.gruppenId, type)}
|
||||
${renderSubSection('Aufgaben', sortByLevelThenName(g.aufgaben || []), 'aufgabe', renderAufgabe, g.gruppenId, type)}
|
||||
${renderSubSection('Strafen', sortByLevelThenName(g.strafen || []), 'strafe', renderStrafe, g.gruppenId, type)}
|
||||
${renderSubSection('Zeitstrafen',sortByName(g.sperren || []), 'zeitstrafe',renderZeitstrafe, g.gruppenId, type)}
|
||||
${renderSubSection('Finisher', sortByName(g.finisher || []), 'finisher', renderFinisher, g.gruppenId, type)}
|
||||
</div>
|
||||
</div>`;
|
||||
}).join('');
|
||||
@@ -864,6 +828,33 @@
|
||||
</div>`;
|
||||
}
|
||||
|
||||
const GESCHLECHT_LABEL = { WEIBLICH: 'Weiblich', DIVERS: 'Divers', MAENNLICH: 'Männlich' };
|
||||
|
||||
function renderFinisher(f, type, gruppenId) {
|
||||
_itemData[f.finisherId] = { ...f, _kind: 'finisher', _gruppenId: gruppenId };
|
||||
const badges = [];
|
||||
if (f.geschlecht) badges.push(`<span class="badge badge-neutral">${esc(GESCHLECHT_LABEL[f.geschlecht] || f.geschlecht)}</span>`);
|
||||
|
||||
const detailRows = [];
|
||||
if (f.text) detailRows.push(`<div class="item-detail-text">${esc(f.text)}</div>`);
|
||||
if (f.benoetigtAktiv && f.benoetigtAktiv.length) detailRows.push(`<div class="item-detail-row"><span class="item-detail-label">Aktiv:</span>${werkzeugChips(f.benoetigtAktiv)}</div>`);
|
||||
if (f.benoetigtPassiv && f.benoetigtPassiv.length) detailRows.push(`<div class="item-detail-row"><span class="item-detail-label">Passiv:</span>${werkzeugChips(f.benoetigtPassiv)}</div>`);
|
||||
if (f.benoetigteToys && f.benoetigteToys.length) detailRows.push(`<div class="item-detail-row"><span class="item-detail-label">Toys:</span>${toyChips(f.benoetigteToys)}</div>`);
|
||||
const actionBtns = type === 'user' ? `
|
||||
<div class="item-action-btns">
|
||||
<button class="btn-item-edit" onclick="openEditItemModal('${esc(f.finisherId)}',event)">✎ Bearbeiten</button>
|
||||
<button class="btn-item-delete" onclick="deleteItem('finisher','${esc(f.finisherId)}','${esc(gruppenId)}',event)">✕ Löschen</button>
|
||||
</div>` : '';
|
||||
|
||||
return `<div class="item" id="item-${esc(f.finisherId)}">
|
||||
<div class="item-row" onclick="toggleItem('${esc(f.finisherId)}')">
|
||||
<span class="item-text">${esc(f.kurzText)}</span>
|
||||
${badges.length ? `<span class="item-badges">${badges.join('')}</span>` : ''}
|
||||
</div>
|
||||
${(detailRows.length || actionBtns) ? `<div class="item-detail">${detailRows.join('')}${actionBtns}</div>` : ''}
|
||||
</div>`;
|
||||
}
|
||||
|
||||
// ── Item toggle (detail panel) ──
|
||||
let openItemId = null;
|
||||
|
||||
@@ -883,8 +874,8 @@
|
||||
}
|
||||
|
||||
// ── Item löschen ──
|
||||
const ITEM_DELETE_URL = { aufgabe: '/aufgabe', strafe: '/strafe', zeitstrafe: '/sperre' };
|
||||
const ITEM_DELETE_FIELD = { aufgabe: 'aufgabeId', strafe: 'strafeId', zeitstrafe: 'sperreId' };
|
||||
const ITEM_DELETE_URL = { aufgabe: '/aufgabe', strafe: '/strafe', zeitstrafe: '/sperre', finisher: '/finisher' };
|
||||
const ITEM_DELETE_FIELD = { aufgabe: 'aufgabeId', strafe: 'strafeId', zeitstrafe: 'sperreId', finisher: 'finisherId' };
|
||||
|
||||
function deleteItem(kind, itemId, gruppenId, event) {
|
||||
event.stopPropagation();
|
||||
@@ -1225,29 +1216,34 @@
|
||||
if (chip) chip.classList.remove('selected');
|
||||
}
|
||||
|
||||
// Toy-Suchmodal
|
||||
const toySearchModal = document.getElementById('toySearchModal');
|
||||
|
||||
document.getElementById('iToyAddBtn').addEventListener('click', openToySearch);
|
||||
document.getElementById('toySearchDoneBtn').addEventListener('click', closeToySearch);
|
||||
toySearchModal.addEventListener('click', e => { if (e.target === toySearchModal) closeToySearch(); });
|
||||
// Toy-Suche (inline)
|
||||
document.getElementById('iToyAddBtn').addEventListener('click', toggleToySearch);
|
||||
document.getElementById('toySearchInput').addEventListener('input', renderToySearchResults);
|
||||
|
||||
function openToySearch() {
|
||||
document.getElementById('toySearchInput').value = '';
|
||||
document.getElementById('toySearchResults').innerHTML = '';
|
||||
document.getElementById('toySearchEmpty').style.display = 'none';
|
||||
toySearchModal.classList.add('open');
|
||||
_loadAvailableToys()
|
||||
.then(() => renderToySearchResults())
|
||||
.catch(() => {
|
||||
document.getElementById('toySearchResults').innerHTML =
|
||||
'<span style="font-size:0.82rem;color:var(--color-muted)">Fehler beim Laden.</span>';
|
||||
});
|
||||
document.getElementById('toySearchInput').focus();
|
||||
function toggleToySearch() {
|
||||
const area = document.getElementById('iToySearchArea');
|
||||
if (area.style.display === 'none') {
|
||||
area.style.display = 'block';
|
||||
document.getElementById('toySearchInput').value = '';
|
||||
document.getElementById('toySearchResults').innerHTML = '';
|
||||
document.getElementById('toySearchEmpty').style.display = 'none';
|
||||
document.getElementById('iToyAddBtn').textContent = '▲ Suche schließen';
|
||||
_loadAvailableToys()
|
||||
.then(() => renderToySearchResults())
|
||||
.catch(() => {
|
||||
document.getElementById('toySearchResults').innerHTML =
|
||||
'<span style="font-size:0.82rem;color:var(--color-muted)">Fehler beim Laden.</span>';
|
||||
});
|
||||
document.getElementById('toySearchInput').focus();
|
||||
} else {
|
||||
closeToySearch();
|
||||
}
|
||||
}
|
||||
|
||||
function closeToySearch() { toySearchModal.classList.remove('open'); }
|
||||
function closeToySearch() {
|
||||
document.getElementById('iToySearchArea').style.display = 'none';
|
||||
document.getElementById('iToyAddBtn').textContent = '+ Toy hinzufügen';
|
||||
}
|
||||
|
||||
function renderToySearchResults() {
|
||||
const query = document.getElementById('toySearchInput').value.trim().toLowerCase();
|
||||
@@ -1297,17 +1293,29 @@
|
||||
let currentItemKind = null; // 'aufgabe' | 'strafe' | 'zeitstrafe'
|
||||
let currentItemEditId = null; // null = neu, sonst ID des zu bearbeitenden Items
|
||||
|
||||
const ITEM_TITLES_NEW = { aufgabe: 'Aufgabe hinzufügen', strafe: 'Strafe hinzufügen', zeitstrafe: 'Zeitstrafe hinzufügen' };
|
||||
const ITEM_TITLES_EDIT = { aufgabe: 'Aufgabe bearbeiten', strafe: 'Strafe bearbeiten', zeitstrafe: 'Zeitstrafe bearbeiten' };
|
||||
const ITEM_TITLES_NEW = { aufgabe: 'Aufgabe hinzufügen', strafe: 'Strafe hinzufügen', zeitstrafe: 'Zeitstrafe hinzufügen', finisher: 'Finisher hinzufügen' };
|
||||
const ITEM_TITLES_EDIT = { aufgabe: 'Aufgabe bearbeiten', strafe: 'Strafe bearbeiten', zeitstrafe: 'Zeitstrafe bearbeiten', finisher: 'Finisher bearbeiten' };
|
||||
|
||||
function _setupItemModal(kind) {
|
||||
const isZeit = kind === 'zeitstrafe';
|
||||
document.getElementById('iLevelRow').style.display = isZeit ? 'none' : 'block';
|
||||
document.getElementById('iWerkzeugAktivRow').style.display = isZeit ? 'none' : 'block';
|
||||
document.getElementById('iWerkzeugPassivRow').style.display = isZeit ? 'none' : 'block';
|
||||
document.getElementById('iMinutenRow').style.display = isZeit ? 'block' : 'none';
|
||||
document.getElementById('iSperreFuerRow').style.display = isZeit ? 'block' : 'none';
|
||||
document.getElementById('iReleaseTextRow').style.display = isZeit ? 'block' : 'none';
|
||||
const isZeit = kind === 'zeitstrafe';
|
||||
const isFinisher = kind === 'finisher';
|
||||
document.querySelector('#iPlaceholderHint .placeholder-hint').innerHTML =
|
||||
isFinisher
|
||||
? 'In Texten können Platzhalter verwendet werden:<br>' +
|
||||
'<code>{AKTIV}</code> – Name der Person die kommt<br>' +
|
||||
'<code>{PASSIV}</code> – Name der Person die zum Kommen bringt'
|
||||
: 'In Texten können Platzhalter verwendet werden:<br>' +
|
||||
'<code>{AKTIV}</code> – Name des aktiven Parts<br>' +
|
||||
'<code>{PASSIV}</code> – Name des passiven Parts';
|
||||
document.getElementById('iGeschlechtRow').style.display = isFinisher ? 'block' : 'none';
|
||||
document.getElementById('iLevelRow').style.display = (!isZeit && !isFinisher) ? 'block' : 'none';
|
||||
document.getElementById('iWerkzeugAktivRow').style.display = (!isZeit && !isFinisher) ? 'block' : 'none';
|
||||
document.getElementById('iWerkzeugPassivRow').style.display = (!isZeit && !isFinisher) ? 'block' : 'none';
|
||||
document.getElementById('iWerkzeugFinisherAktivRow').style.display = isFinisher ? 'block' : 'none';
|
||||
document.getElementById('iWerkzeugFinisherPassivRow').style.display = isFinisher ? 'block' : 'none';
|
||||
document.getElementById('iMinutenRow').style.display = isZeit ? 'block' : 'none';
|
||||
document.getElementById('iSperreFuerRow').style.display = isZeit ? 'block' : 'none';
|
||||
document.getElementById('iReleaseTextRow').style.display = isZeit ? 'block' : 'none';
|
||||
}
|
||||
|
||||
function _resetItemFields() {
|
||||
@@ -1319,9 +1327,12 @@
|
||||
document.getElementById('iMinVon').value = '';
|
||||
document.getElementById('iMinBis').value = '';
|
||||
document.getElementById('iReleaseText').value = '';
|
||||
document.querySelectorAll('#iWerkzeugAktiv input').forEach(cb => cb.checked = false);
|
||||
document.querySelectorAll('#iWerkzeugPassiv input').forEach(cb => cb.checked = false);
|
||||
document.querySelectorAll('#iSperreFuer input').forEach(cb => cb.checked = false);
|
||||
document.querySelectorAll('#iWerkzeugAktiv input').forEach(cb => cb.checked = false);
|
||||
document.querySelectorAll('#iWerkzeugPassiv input').forEach(cb => cb.checked = false);
|
||||
document.querySelectorAll('#iWerkzeugFinisherAktiv input').forEach(cb => cb.checked = false);
|
||||
document.querySelectorAll('#iWerkzeugFinisherPassiv input').forEach(cb => cb.checked = false);
|
||||
document.querySelectorAll('#iSperreFuer input').forEach(cb => cb.checked = false);
|
||||
document.querySelectorAll('#iGeschlecht input').forEach(rb => rb.checked = false);
|
||||
_selectedToys = [];
|
||||
renderSelectedToys();
|
||||
document.getElementById('itemModalError').style.display = 'none';
|
||||
@@ -1359,6 +1370,13 @@
|
||||
document.getElementById('iSekBis').value = d.sekundenBis != null ? d.sekundenBis : '';
|
||||
(d.benoetigtAktiv || []).forEach(w => { const cb = document.querySelector(`#iWerkzeugAktiv input[value="${w}"]`); if (cb) cb.checked = true; });
|
||||
(d.benoetigtPassiv || []).forEach(w => { const cb = document.querySelector(`#iWerkzeugPassiv input[value="${w}"]`); if (cb) cb.checked = true; });
|
||||
} else if (d._kind === 'finisher') {
|
||||
(d.benoetigtAktiv || []).forEach(w => { const cb = document.querySelector(`#iWerkzeugFinisherAktiv input[value="${w}"]`); if (cb) cb.checked = true; });
|
||||
(d.benoetigtPassiv || []).forEach(w => { const cb = document.querySelector(`#iWerkzeugFinisherPassiv input[value="${w}"]`); if (cb) cb.checked = true; });
|
||||
if (d.geschlecht) {
|
||||
const rb = document.querySelector(`#iGeschlecht input[value="${d.geschlecht}"]`);
|
||||
if (rb) rb.checked = true;
|
||||
}
|
||||
} else {
|
||||
document.getElementById('iMinVon').value = d.minutenVon != null ? d.minutenVon : '';
|
||||
document.getElementById('iMinBis').value = d.minutenBis != null ? d.minutenBis : '';
|
||||
@@ -1372,7 +1390,11 @@
|
||||
document.getElementById('iKurzText').focus();
|
||||
}
|
||||
|
||||
function closeItemModal() { itemModal.classList.remove('open'); }
|
||||
function closeItemModal() { itemModal.classList.remove('open'); closeToySearch(); document.getElementById('iPlaceholderHint').style.display = 'none'; }
|
||||
function togglePlaceholderHint() {
|
||||
const el = document.getElementById('iPlaceholderHint');
|
||||
el.style.display = el.style.display === 'none' ? 'block' : 'none';
|
||||
}
|
||||
|
||||
document.getElementById('itemCancelBtn').addEventListener('click', closeItemModal);
|
||||
itemModal.addEventListener('click', e => { if (e.target === itemModal) closeItemModal(); });
|
||||
@@ -1408,6 +1430,19 @@
|
||||
url = isEdit ? `${base}/${currentItemEditId}` : base;
|
||||
method = isEdit ? 'PUT' : 'POST';
|
||||
|
||||
} else if (kind === 'finisher') {
|
||||
const geschlecht = document.querySelector('#iGeschlecht input:checked')?.value;
|
||||
if (!geschlecht) { showItemError('Bitte ein Geschlecht auswählen.'); return; }
|
||||
payload = {
|
||||
kurzText, text, geschlecht,
|
||||
gruppeId: isEdit ? undefined : currentItemGruppeId,
|
||||
benoetigtAktiv: checkedValues('iWerkzeugFinisherAktiv'),
|
||||
benoetigtPassiv: checkedValues('iWerkzeugFinisherPassiv'),
|
||||
benoetigteToys: _selectedToys.map(t => ({ toyId: t.toyId }))
|
||||
};
|
||||
url = isEdit ? `/finisher/${currentItemEditId}` : '/finisher';
|
||||
method = isEdit ? 'PUT' : 'POST';
|
||||
|
||||
} else {
|
||||
const minVon = document.getElementById('iMinVon').value.trim();
|
||||
if (!minVon) { showItemError('Bitte eine Mindestdauer in Minuten angeben.'); return; }
|
||||
@@ -1422,7 +1457,7 @@
|
||||
minutenBis: minBis ? parseInt(minBis, 10) : null,
|
||||
releaseText: document.getElementById('iReleaseText').value.trim() || null,
|
||||
sperreFuer,
|
||||
benoetigteToys: Array.from(_selectedToyIds).map(id => ({ toyId: id }))
|
||||
benoetigteToys: _selectedToys.map(t => ({ toyId: t.toyId }))
|
||||
};
|
||||
url = isEdit ? `/sperre/${currentItemEditId}` : '/sperre';
|
||||
method = isEdit ? 'PUT' : 'POST';
|
||||
@@ -1558,27 +1593,12 @@
|
||||
// ── ESC schließt alle Modals ──
|
||||
document.addEventListener('keydown', e => {
|
||||
if (e.key !== 'Escape') return;
|
||||
if (toySearchModal.classList.contains('open')) { closeToySearch(); return; }
|
||||
if (publishModal.classList.contains('open')) { closePublishModal(); return; }
|
||||
if (gruppeModal.classList.contains('open')) { closeGruppeModal(); return; }
|
||||
if (itemModal.classList.contains('open')) { closeItemModal(); return; }
|
||||
});
|
||||
|
||||
// ── Burger menu ──
|
||||
const sidebar = document.getElementById('sidebar');
|
||||
const burgerBtn = document.getElementById('burgerBtn');
|
||||
const overlay = document.getElementById('overlay');
|
||||
function openMenu() {
|
||||
sidebar.classList.add('open'); overlay.classList.add('visible');
|
||||
burgerBtn.classList.add('open'); burgerBtn.setAttribute('aria-label', 'Menü schließen');
|
||||
}
|
||||
function closeMenu() {
|
||||
sidebar.classList.remove('open'); overlay.classList.remove('visible');
|
||||
burgerBtn.classList.remove('open'); burgerBtn.setAttribute('aria-label', 'Menü öffnen');
|
||||
}
|
||||
burgerBtn.addEventListener('click', () => sidebar.classList.contains('open') ? closeMenu() : openMenu());
|
||||
overlay.addEventListener('click', closeMenu);
|
||||
sidebar.querySelectorAll('a').forEach(l => l.addEventListener('click', () => { if (window.innerWidth <= 768) closeMenu(); }));
|
||||
</script>
|
||||
<script src="/js/sidebar.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user