Version 2.0: Agenda-Folien für Online-Meetings (Hybrid-Chapter)

Neue Agenda-Punkte im Steuerpult (frei per Drag & Drop sortierbar, wie
die Mitgliederliste), pro Punkt entweder als hochgeladenes Bild oder als
Live-Einbettung aus Zoho Show. Mitglieder-/Besucher-Vorstellungsrunde und
eine neue Marketing-/Ergebnisrunde (gleiche Reihenfolge, ohne Timer) sind
eingebaute Agenda-Punkte und lassen sich genauso einsortieren. Der
"Weiter"-Button folgt jetzt der kompletten Agenda-Reihenfolge statt nur
Mitglieder- und Besucherrunde.

Unterwegs behobene Bugs: unsichtbarer "Anzeigen"-Button (falsche
Button-Klasse), fehlendes chapters/<code>/-Präfix beim Bild-Upload,
Race-Condition beim Speichern eines gerade erst ausgewählten Bildes,
Agenda-Reihenfolge-Duplikate bei bestehenden Chaptern.

Anleitung um Agenda-Abschnitt ergänzt, plus Korrekturen zu Ordnername,
Aktivierungs-Kontakt, Admin-Panel-URL und Offline-Hinweis für
Live-Einbettungen. Screenshots-Ordner (inkl. bisher nie gepushter
Bestandsbilder) erstmals vollständig committet.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Christian Heubaum
2026-08-19 18:59:22 +02:00
parent b40f384123
commit 580725f2f7
22 changed files with 1527 additions and 152 deletions

View File

@@ -102,6 +102,7 @@
<div class="tabs">
<div class="tab active" onclick="switchAdminTab('stammvertreter')">Stammvertreter</div>
<div class="tab" onclick="switchAdminTab('mitglieder')">Mitglieder</div>
<div class="tab" onclick="switchAdminTab('agenda')">Agenda</div>
<div class="tab" id="superadmin-tab" onclick="switchAdminTab('superadmin')" style="display:none;">Superadmin</div>
<div class="tab" onclick="switchAdminTab('einstellungen')">Einstellungen</div>
</div>
@@ -146,6 +147,27 @@
</div>
</div>
<!-- ============================================================ AGENDA -->
<div id="tab-agenda" class="tab-content">
<div class="card">
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:14px;">
<div class="card-title" style="margin:0;">Agenda-Folien (Online-Meeting)</div>
<div style="display:flex;gap:8px;">
<button class="btn btn-secondary btn-sm" onclick="fetchAgendaAdmin()">🔄 Vom Server laden</button>
<button class="btn btn-primary btn-sm" onclick="uploadAgendaAdmin()">📤 Auf Server hochladen</button>
</div>
</div>
<p style="font-size:0.85rem;color:var(--muted);margin-bottom:12px;">
Punkte für den Online-Meeting-Ablauf (z.B. Begrüßung, DSGVO, BNI-Zahlen, Events) – als Bild oder als Live-Einbettung
aus Zoho Show. Die Reihenfolge hier ist nur der Katalog; welche Punkte in welcher Reihenfolge live gezeigt werden,
stellt die Moderatorin frei im Steuerpult (index.html) ein.
</p>
<div class="status-msg" id="agenda-status"></div>
<div id="admin-agenda-list" style="margin-top:10px;"><div style="color:var(--muted);font-size:0.88rem;">Lade…</div></div>
<button class="btn btn-secondary btn-sm w-full" style="margin-top:12px;" onclick="openAddAgendaItem()">+ Agenda-Punkt hinzufügen</button>
</div>
</div>
<!-- ============================================================ SUPERADMIN -->
<div id="tab-superadmin" class="tab-content">
<div class="card">
@@ -291,6 +313,42 @@
</div>
</div>
<!-- Agenda Item Modal -->
<div class="modal-overlay" id="modal-agenda-item">
<div class="modal">
<div class="modal-header">
<div class="modal-title" id="agenda-item-modal-title">Agenda-Punkt</div>
<button class="modal-close" onclick="closeAdminModal('modal-agenda-item')">✕</button>
</div>
<input type="hidden" id="ai-id">
<label>Bezeichnung</label>
<input type="text" id="ai-label" placeholder="z.B. Begrüßung">
<label>Anzeigeart</label>
<select id="ai-type" onchange="updateAgendaItemTypeUI()">
<option value="image">Bild (Export, wird hochgeladen)</option>
<option value="embed">Live-Einbettung (Zoho Show o.ä.)</option>
</select>
<div id="ai-image-row">
<label>Bild</label>
<div class="photo-actions">
<img id="ai-image-thumb" class="photo-thumb" style="width:80px;height:80px;border-radius:8px;display:none;" src="" alt="">
<label class="btn-file-label">📁 Bild wählen<input type="file" id="ai-image-file" accept="image/*" style="display:none" onchange="handleAgendaImageFile(this)"></label>
</div>
<div id="ai-image-thumb-hint" style="display:none;font-size:0.78rem;color:#d97706;margin-top:6px;"></div>
</div>
<div id="ai-embed-row" style="display:none;">
<label>Einbettungs-URL</label>
<input type="text" id="ai-embed-url" placeholder="https://show.zoho.eu/publish/...">
<p style="font-size:0.78rem;color:var(--muted);margin-top:4px;">In Zoho Show: Datei → Freigeben/Veröffentlichen → Einbetten, Link hier einfügen.</p>
</div>
<div class="modal-footer">
<button class="btn btn-danger btn-sm" id="ai-delete-btn" onclick="deleteAgendaItem()" style="display:none;margin-right:auto;">Löschen</button>
<button class="btn btn-ghost" onclick="closeAdminModal('modal-agenda-item')">Abbrechen</button>
<button class="btn btn-primary" onclick="saveAgendaItem()">Speichern</button>
</div>
</div>
</div>
<!-- Import from Chapter Modal -->
<div class="modal-overlay" id="modal-import-chapter">
<div class="modal">
@@ -399,6 +457,7 @@ function switchAdminTab(tab) {
document.getElementById(`tab-${tab}`).classList.add('active');
if (tab === 'stammvertreter') renderSvList();
if (tab === 'mitglieder') renderMembersList();
if (tab === 'agenda') renderAgendaAdminList();
if (tab === 'superadmin') { loadAllChapters(); loadCurrentVersion(); }
if (tab === 'einstellungen') renderSettings();
}
@@ -780,6 +839,241 @@ async function uploadMembersAdmin() {
}
}
// ============================================================
// AGENDA-FOLIEN (Online-Meeting-Ablauf)
// ============================================================
let _agendaImageDataUrl = null;
let _agendaImageChanged = false;
let _agendaImageProcessing = null; // Promise, solange ein gewähltes Bild noch verkleinert wird
function slugify(s) {
const map = { ä:'ae', ö:'oe', ü:'ue', ß:'ss' };
return (s || '').toLowerCase().trim()
.replace(/[äöüß]/g, c => map[c])
.replace(/[^a-z0-9]+/g, '-')
.replace(/^-+|-+$/g, '') || 'punkt';
}
function renderAgendaAdminList() {
const state = loadState();
const container = document.getElementById('admin-agenda-list');
const items = state.agendaCatalog || [];
if (!items.length) {
container.innerHTML = `<div style="color:var(--muted);font-size:0.88rem;">Noch keine Agenda-Punkte. Mit "+ Agenda-Punkt hinzufügen" starten.</div>`;
return;
}
container.innerHTML = '';
items.forEach(it => {
const div = document.createElement('div');
div.className = 'member-item';
div.style.cursor = 'pointer';
div.title = 'Bearbeiten';
const typeLabel = it.type === 'embed' ? 'Live-Einbettung' : 'Bild';
div.innerHTML = `
<div style="flex:1;min-width:0;">
<div style="font-weight:600;font-size:0.88rem;">${escHtml(it.label || it.id)}</div>
<div style="font-size:0.75rem;color:var(--muted);">${typeLabel}</div>
</div>
<button class="btn btn-ghost btn-sm">✎</button>
`;
div.onclick = () => editAgendaItem(it.id);
container.appendChild(div);
});
}
function openAddAgendaItem() {
document.getElementById('ai-id').value = '';
document.getElementById('agenda-item-modal-title').textContent = 'Agenda-Punkt hinzufügen';
document.getElementById('ai-label').value = '';
document.getElementById('ai-type').value = 'image';
document.getElementById('ai-embed-url').value = '';
document.getElementById('ai-delete-btn').style.display = 'none';
_agendaImageDataUrl = null; _agendaImageChanged = false;
document.getElementById('ai-image-thumb').style.display = 'none';
document.getElementById('ai-image-thumb-hint').style.display = 'none';
updateAgendaItemTypeUI();
openAdminModal('modal-agenda-item');
}
function editAgendaItem(id) {
const state = loadState();
const it = (state.agendaCatalog || []).find(a => a.id === id);
if (!it) return;
document.getElementById('ai-id').value = it.id;
document.getElementById('agenda-item-modal-title').textContent = 'Agenda-Punkt bearbeiten';
document.getElementById('ai-label').value = it.label || '';
document.getElementById('ai-type').value = it.type || 'image';
document.getElementById('ai-embed-url').value = it.embedUrl || '';
document.getElementById('ai-delete-btn').style.display = 'inline-flex';
_agendaImageDataUrl = null; _agendaImageChanged = false;
const thumb = document.getElementById('ai-image-thumb');
const thumbHint = document.getElementById('ai-image-thumb-hint');
if (it.imagePath) {
thumb.onerror = () => {
thumb.style.display = 'none';
if (thumbHint) { thumbHint.textContent = '⚠ Bild nicht auf dem Server gefunden – bitte neu hochladen.'; thumbHint.style.display = 'block'; }
};
thumb.onload = () => { if (thumbHint) thumbHint.style.display = 'none'; };
if (thumbHint) thumbHint.style.display = 'none';
thumb.src = it.imagePath.startsWith('http') ? it.imagePath : giteaUrl(`chapters/${activeChapter.code}/${it.imagePath}`);
thumb.style.display = 'block';
} else {
thumb.style.display = 'none';
if (thumbHint) thumbHint.style.display = 'none';
}
updateAgendaItemTypeUI();
openAdminModal('modal-agenda-item');
}
function updateAgendaItemTypeUI() {
const type = document.getElementById('ai-type').value;
document.getElementById('ai-image-row').style.display = type === 'image' ? 'block' : 'none';
document.getElementById('ai-embed-row').style.display = type === 'embed' ? 'block' : 'none';
}
function handleAgendaImageFile(input) {
const file = input.files && input.files[0];
if (!file) return;
const hint = document.getElementById('ai-image-thumb-hint');
if (hint) { hint.textContent = 'Bild wird verarbeitet…'; hint.style.color = 'var(--muted)'; hint.style.display = 'block'; }
// Auf eine für Vollbild-Anzeige ausreichende Größe verkleinern/komprimieren, damit der
// Upload sicher unter dem Größenlimit der Gitea-Contents-API bleibt (typischerweise ~1 MB/Datei).
// _agendaImageProcessing merkt sich das laufende Promise, damit saveAgendaItem() nicht zu früh
// speichert, während das Bild noch verarbeitet wird (führte sonst zu einem stillen "kein Bild gewählt").
_agendaImageProcessing = resizePhotoToBase64(file, 1920).then(b64 => {
_agendaImageDataUrl = b64;
_agendaImageChanged = true;
const thumb = document.getElementById('ai-image-thumb');
thumb.src = b64;
thumb.style.display = 'block';
if (hint) {
const kb = Math.round((b64.length * 0.75) / 1024);
hint.textContent = `Für den Upload verkleinert auf max. 1920px, ~${kb} KB.`;
hint.style.color = 'var(--muted)';
hint.style.display = 'block';
}
}).catch(() => alert('Bild konnte nicht gelesen werden.'))
.finally(() => { _agendaImageProcessing = null; });
input.value = '';
}
async function uploadAgendaImage(path, dataUrl, token) {
const content = dataUrl.split(',')[1];
const url = giteaAuthUrl(path, token);
let sha = null;
const shaRes = await fetch(url);
if (shaRes.ok) sha = (await shaRes.json()).sha;
const body = { message: `Agenda-Bild aktualisiert ${new Date().toLocaleDateString('de')}`, content };
if (sha) body.sha = sha;
const res = await fetch(url, { method: sha ? 'PUT' : 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) });
if (!res.ok) { const t = await res.text(); throw new Error(`${res.status}: ${t.slice(0, 80)}`); }
}
async function saveAgendaItem() {
const label = document.getElementById('ai-label').value.trim();
if (!label) { alert('Bitte eine Bezeichnung eingeben.'); return; }
const type = document.getElementById('ai-type').value;
if (_agendaImageProcessing) {
const statusEl = document.getElementById('agenda-status');
statusEl.textContent = 'Bild wird noch verarbeitet…'; statusEl.style.color = 'var(--muted)';
await _agendaImageProcessing;
}
const state = loadState();
if (!state.agendaCatalog) state.agendaCatalog = [];
let id = document.getElementById('ai-id').value;
if (!id) {
const base = slugify(label);
const ids = new Set(state.agendaCatalog.map(a => a.id));
let candidate = base, n = 1;
while (ids.has(candidate)) candidate = `${base}-${++n}`;
id = candidate;
}
const existing = state.agendaCatalog.find(a => a.id === id) || {};
const item = { id, label, type };
if (type === 'embed') {
const url = document.getElementById('ai-embed-url').value.trim();
if (!url) { alert('Bitte eine Einbettungs-URL eingeben.'); return; }
item.embedUrl = url;
} else {
item.imagePath = existing.imagePath || `agenda/${id}.jpg`;
if (!_agendaImageChanged && !existing.imagePath) { alert('Bitte ein Bild wählen.'); return; }
}
const statusEl = document.getElementById('agenda-status');
if (type === 'image' && _agendaImageChanged && _agendaImageDataUrl) {
const token = getAdminToken();
if (!token) { alert('Bitte zuerst Admin-Token in den Einstellungen speichern.'); return; }
statusEl.textContent = 'Lade Bild hoch…'; statusEl.style.color = 'var(--muted)';
try {
await uploadAgendaImage(`chapters/${activeChapter.code}/${item.imagePath}`, _agendaImageDataUrl, token);
} catch(e) {
statusEl.textContent = `Fehler beim Bild-Upload: ${e.message}`; statusEl.style.color = '#dc2626';
alert(`Bild-Upload fehlgeschlagen: ${e.message}\n\nDer Agenda-Punkt wurde NICHT gespeichert.`);
return;
}
}
const idx = state.agendaCatalog.findIndex(a => a.id === id);
if (idx >= 0) state.agendaCatalog[idx] = item; else state.agendaCatalog.push(item);
saveState(state);
closeAdminModal('modal-agenda-item');
renderAgendaAdminList();
statusEl.textContent = '✓ Lokal gespeichert – "Auf Server hochladen" nicht vergessen, damit es im Steuerpult ankommt.';
statusEl.style.color = 'var(--success)';
}
function deleteAgendaItem() {
const id = document.getElementById('ai-id').value;
if (!id) return;
if (!confirm('Diesen Agenda-Punkt wirklich löschen?')) return;
const state = loadState();
state.agendaCatalog = (state.agendaCatalog || []).filter(a => a.id !== id);
saveState(state);
closeAdminModal('modal-agenda-item');
renderAgendaAdminList();
}
async function fetchAgendaAdmin() {
const statusEl = document.getElementById('agenda-status');
statusEl.textContent = 'Lade vom Server…'; statusEl.style.color = 'var(--muted)';
try {
const res = await fetch(giteaUrl(`chapters/${activeChapter.code}/agenda.json`), { cache: 'no-store' });
if (!res.ok) { statusEl.textContent = 'Noch keine Agenda auf dem Server.'; return; }
const data = await res.json();
const state = loadState();
state.agendaCatalog = Array.isArray(data.items) ? data.items : [];
saveState(state);
statusEl.textContent = `✓ ${state.agendaCatalog.length} Punkte geladen`; statusEl.style.color = 'var(--success)';
renderAgendaAdminList();
} catch(e) { statusEl.textContent = 'Verbindungsfehler.'; statusEl.style.color = '#dc2626'; }
}
async function uploadAgendaAdmin() {
const token = getAdminToken();
if (!token) { alert('Bitte zuerst Admin-Token in den Einstellungen speichern.'); return; }
const statusEl = document.getElementById('agenda-status');
statusEl.textContent = 'Lädt hoch…'; statusEl.style.color = 'var(--muted)';
try {
const state = loadState();
const data = { items: state.agendaCatalog || [] };
const content = btoa(unescape(encodeURIComponent(JSON.stringify(data, null, 2))));
const path = `chapters/${activeChapter.code}/agenda.json`;
const url = giteaAuthUrl(path, token);
let sha = null;
const shaRes = await fetch(url);
if (shaRes.ok) sha = (await shaRes.json()).sha;
const body = { message: `Agenda aktualisiert ${new Date().toLocaleDateString('de')}`, content };
if (sha) body.sha = sha;
const res = await fetch(url, { method: sha ? 'PUT' : 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) });
if (res.ok) { statusEl.textContent = `✓ ${data.items.length} Agenda-Punkte hochgeladen`; statusEl.style.color = 'var(--success)'; }
else { const t = await res.text(); statusEl.textContent = `Fehler ${res.status}: ${t.slice(0, 80)}`; statusEl.style.color = '#dc2626'; }
} catch(e) { statusEl.textContent = `Fehler: ${e.message}`; statusEl.style.color = '#dc2626'; }
}
// ============================================================
// SUPERADMIN
// ============================================================

View File

@@ -118,7 +118,7 @@
<div style="font-size:2.5rem; margin-bottom:8px;">🌟</div>
<h1>BNI Vorstellungsrunde</h1>
<div class="subtitle">Benutzeranleitung für Chapter-Admins</div>
<div class="badge">Version 1.2 · April 2026</div>
<div class="badge">Version 1.5 · August 2026</div>
</div>
<div class="toc">
@@ -135,6 +135,10 @@
<li><a href="#offline">Offline-Nutzung</a></li>
<li><a href="#update">Updates einspielen</a></li>
<li><a href="#timer-schalter">Zeitanzeige deaktivieren</a></li>
<li><a href="#augen-timer">8-Augen-Gespräche Timer</a></li>
<li><a href="#mitglieder-sync">Mitglieder mit BNI-Website synchronisieren</a></li>
<li><a href="#import-export">Import / Export &amp; Backup</a></li>
<li><a href="#agenda">Agenda-Folien für Online-Meetings (Hybrid-Chapter)</a></li>
</ol>
</div>
@@ -149,14 +153,17 @@
<div class="card">
<div class="steps">
<div class="step"><p>Den Ordner <code>BNI Sonne</code> im Finder öffnen.</p></div>
<div class="step"><p>Die Datei <strong>start.command</strong> doppelklicken — es öffnet sich kurz ein Terminal-Fenster, dann startet Chrome automatisch mit dem Tool.</p></div>
<div class="step"><p>Das Terminal-Fenster im Hintergrund lassen (nicht schließen, solange du das Tool nutzt).</p></div>
<div class="step"><p>Den Ordner <code>bni-vorstellungsrunde</code> im Finder öffnen.</p></div>
<div class="step"><p>Die Datei <strong>index.html</strong> per Doppelklick öffnen — sie startet direkt im Standardbrowser.</p></div>
</div>
</div>
<div class="info">
<strong>Alternative über das Terminal:</strong> Statt <code>index.html</code> direkt zu öffnen, kann auch die Datei <strong>start.command</strong> doppelgeklickt werden — es öffnet sich kurz ein Terminal-Fenster, das im Hintergrund einen lokalen Server startet, dann startet Chrome automatisch mit dem Tool. Das Terminal-Fenster muss dabei offen bleiben, solange das Tool genutzt wird. Diese Variante ist nur nötig, falls das direkte Öffnen von <code>index.html</code> mal nicht funktioniert (z. B. Admin-Panel unter <a href="#admin">Admin-Panel öffnen</a>).
</div>
<div class="tip">
<strong>Hinweis:</strong> Beim ersten Doppelklick erscheint eventuell eine Sicherheitswarnung von macOS. Dann: Rechtsklick auf <code>start.command</code> → „Öffnen" → „Öffnen" bestätigen. Ab dem zweiten Mal klappt der Doppelklick direkt.
<strong>Hinweis zu start.command:</strong> Beim ersten Doppelklick erscheint eventuell eine Sicherheitswarnung von macOS. Dann: Rechtsklick auf <code>start.command</code> → „Öffnen" → „Öffnen" bestätigen. Ab dem zweiten Mal klappt der Doppelklick direkt.
</div>
<div class="mockup">
@@ -164,7 +171,7 @@
<div class="mockup-dot" style="background:#ff5f57;"></div>
<div class="mockup-dot" style="background:#febc2e;"></div>
<div class="mockup-dot" style="background:#28c840;"></div>
<span style="color:rgba(255,255,255,0.4);font-size:0.78rem;margin-left:8px;">Terminal</span>
<span style="color:rgba(255,255,255,0.4);font-size:0.78rem;margin-left:8px;">Terminal (nur bei der Alternative über start.command)</span>
</div>
<div class="mockup-body">
<p style="color:#4ade80;font-size:0.82rem;font-family:monospace;">$ python3 -m http.server 8181</p>
@@ -186,7 +193,7 @@
<div class="card">
<div class="steps">
<div class="step"><p>Den <strong>Lizenzcode</strong> deines Chapters eingeben (erhältst du vom Administrator).</p></div>
<div class="step"><p>Den <strong>Lizenzcode</strong> deines Chapters eingeben (erhältst du vom Administrator <a href="mailto:support@digiseed.de">support@digiseed.de</a>).</p></div>
<div class="step"><p>Auf <strong>„Aktivieren"</strong> klicken. Das Tool lädt einmalig die Chapter-Daten vom Server.</p></div>
<div class="step"><p>Nach erfolgreicher Aktivierung öffnet sich direkt die Steuerungsansicht.</p></div>
</div>
@@ -202,8 +209,8 @@
<div class="mockup-body">
<div class="mock-activation">
<h3>BNI Vorstellungsrunde</h3>
<p>Bitte Chapter-Code eingeben</p>
<div style="margin-bottom:8px;"><input class="mock-input" placeholder="z. B. sonne-7x4m9k" readonly></div>
<p>Bitte gib deinen Lizenzcode ein, um dein Chapter freizuschalten.</p>
<div style="margin-bottom:8px;"><input class="mock-input" placeholder="chapter-lizenzcode" readonly></div>
<button class="mock-btn-red">Aktivieren</button>
</div>
</div>
@@ -232,7 +239,7 @@
</div>
<div class="highlight-box">
Beim Öffnen des Tools wird automatisch ein zweites Tab für das Display geöffnet. Ziehe dieses Tab auf den Beamer-Bildschirm und drücke <strong>F11</strong> für Vollbild.
Im Steuerungs-Fenster oben in der Kopfzeile auf <strong>„🖥 Anzeige öffnen"</strong> klicken — das Display öffnet sich in einem neuen Tab. Ziehe dieses Tab auf den Beamer-Bildschirm und drücke <strong>F11</strong> für Vollbild.
</div>
<div class="mockup">
@@ -242,16 +249,28 @@
<div class="mockup-dot" style="background:#28c840;"></div>
<span style="color:rgba(255,255,255,0.4);font-size:0.78rem;margin-left:8px;">Display-Ansicht (Beamer)</span>
</div>
<div class="mockup-body">
<div class="mock-timer">
<div style="color:rgba(255,255,255,0.4);font-size:0.75rem;margin-bottom:10px;">JETZT SPRICHT</div>
<div class="mock-timer-ring">
<span class="mock-timer-num">45</span>
</div>
<div class="mock-timer-name">Maria Mustermann</div>
<div class="mock-timer-company">Muster GmbH · Steuerberatung</div>
<div style="color:rgba(255,255,255,0.3);font-size:0.75rem;margin-top:8px;">Nächster: Hans Müller</div>
</div>
<div class="mockup-body" style="padding:0;background:#0a1220;">
<img src="screenshots/display-live.png" alt="Display-Ansicht mit laufendem Timer" style="width:100%;display:block;">
</div>
</div>
<div class="highlight-box">
<strong>Ab Version 1.5:</strong> Zusätzlich zum Ring wird die Restzeit oben in großen Ziffern eingeblendet — gut sichtbar, auch wenn jemand vor dem Podium steht. Bei ≤ 15 s wird die Karte gelb, bei ≤ 5 s rot, am Ende ertönt ein Glockenton.
</div>
<div class="tip">
<strong>🔔 Ton aktivieren:</strong> Beim ersten Öffnen des Display-Fensters erscheint oben ein roter Button <strong>„🔔 Ton aktivieren"</strong>. Einmal klicken — damit erlaubt der Browser das Abspielen des Glockentons. Ohne diesen Klick bleibt die App stumm (technische Einschränkung von Browsern gegen ungewollte Autoplay-Sounds).
</div>
<div class="mockup">
<div class="mockup-bar">
<div class="mockup-dot" style="background:#ff5f57;"></div>
<div class="mockup-dot" style="background:#febc2e;"></div>
<div class="mockup-dot" style="background:#28c840;"></div>
<span style="color:rgba(255,255,255,0.4);font-size:0.78rem;margin-left:8px;">Display-Ansicht – Ton aktivieren</span>
</div>
<div class="mockup-body" style="padding:0;background:#0a1220;">
<img src="screenshots/display-ton-aktivieren.png" alt="Display-Ansicht mit Ton-aktivieren-Button" style="width:100%;display:block;">
</div>
</div>
</div>
@@ -278,36 +297,54 @@
<div class="mockup-dot" style="background:#ff5f57;"></div>
<div class="mockup-dot" style="background:#febc2e;"></div>
<div class="mockup-dot" style="background:#28c840;"></div>
<span style="color:rgba(255,255,255,0.4);font-size:0.78rem;margin-left:8px;">Steuerung – Reihenfolge</span>
<span style="color:rgba(255,255,255,0.4);font-size:0.78rem;margin-left:8px;">Steuerungs-Fenster – Reihenfolge</span>
</div>
<div class="mockup-body">
<div style="font-size:0.72rem;color:rgba(255,255,255,0.35);font-weight:700;letter-spacing:1px;text-transform:uppercase;margin-bottom:10px;">Reihenfolge (Ziehen zum Sortieren)</div>
<!-- Nächster -->
<div style="display:flex;align-items:center;gap:10px;padding:10px 12px;background:rgba(255,255,255,0.1);border:1px solid rgba(255,255,255,0.2);border-radius:10px;margin-bottom:6px;">
<span style="color:rgba(255,255,255,0.25);font-size:1rem;">⠿</span>
<div style="width:38px;height:38px;border-radius:50%;background:#1a2744;display:flex;align-items:center;justify-content:center;font-size:0.75rem;font-weight:700;color:white;flex-shrink:0;">AM</div>
<div style="flex:1;"><div style="font-size:0.85rem;font-weight:700;color:white;">Anna Müller</div><div style="font-size:0.72rem;color:rgba(255,255,255,0.45);">Steuerberatung</div></div>
<span style="background:#374151;color:white;font-size:0.68rem;font-weight:700;padding:2px 8px;border-radius:6px;letter-spacing:0.5px;">NÄCHSTER</span>
<button style="background:rgba(255,255,255,0.08);border:none;border-radius:6px;padding:5px 8px;color:rgba(255,255,255,0.6);cursor:pointer;font-size:0.85rem;">↺</button>
<button style="background:rgba(204,0,0,0.15);border:none;border-radius:6px;padding:5px 8px;color:rgba(255,100,100,0.7);cursor:pointer;font-size:0.85rem;">🚫</button>
<div class="mockup-body" style="padding:0;background:#0a1220;">
<img src="screenshots/steuerung-uebersicht.png" alt="Steuerungs-Fenster mit Mitgliederliste" style="width:100%;display:block;">
</div>
</div>
<!-- Redezeit -->
<div class="card" style="margin-top:24px;">
<p style="font-weight:700;font-size:0.95rem;margin-bottom:10px;">Redezeit anpassen</p>
<p style="font-size:0.88rem;color:var(--muted);margin-bottom:14px;">Standard-Redezeit für alle Mitglieder oder abweichende Zeit pro Person setzen.</p>
<p style="font-weight:700;font-size:0.85rem;margin-bottom:8px;">A) Standardzeit für alle</p>
<div class="steps">
<div class="step"><p>Oben in der Kopfzeile des Steuerungs-Fensters auf das Zeit-Feld <strong>„⏱ 0:50"</strong> (bzw. den aktuellen Wert) klicken.</p></div>
<div class="step"><p>Im Dialog die neue Zeit im Format <code>M:SS</code> (z. B. <code>1:00</code>) oder als Minuten (z. B. <code>1</code>) eingeben.</p></div>
<div class="step"><p>Mit <strong>OK</strong> bestätigen — die neue Zeit gilt sofort für alle Mitglieder ohne individuelle Zeit.</p></div>
</div>
<div class="mockup">
<div class="mockup-bar">
<div class="mockup-dot" style="background:#ff5f57;"></div>
<div class="mockup-dot" style="background:#febc2e;"></div>
<div class="mockup-dot" style="background:#28c840;"></div>
<span style="color:rgba(255,255,255,0.4);font-size:0.78rem;margin-left:8px;">Dialog – Standard-Redezeit setzen</span>
</div>
<!-- Abwesend -->
<div style="display:flex;align-items:center;gap:10px;padding:10px 12px;background:rgba(204,0,0,0.08);border:1px solid rgba(204,0,0,0.2);border-radius:10px;margin-bottom:6px;opacity:0.6;">
<span style="color:rgba(255,255,255,0.25);font-size:1rem;">⠿</span>
<div style="width:38px;height:38px;border-radius:50%;background:#7f1d1d;display:flex;align-items:center;justify-content:center;font-size:0.75rem;font-weight:700;color:white;flex-shrink:0;">KS</div>
<div style="flex:1;"><div style="font-size:0.85rem;font-weight:700;color:rgba(255,255,255,0.5);">Klaus Schmidt</div><div style="font-size:0.72rem;color:rgba(255,255,255,0.3);">IT-Systeme</div></div>
<button style="background:rgba(255,255,255,0.08);border:none;border-radius:6px;padding:5px 8px;color:rgba(255,255,255,0.4);cursor:pointer;font-size:0.85rem;">↺</button>
<button style="background:rgba(204,0,0,0.3);border:none;border-radius:6px;padding:5px 8px;color:#f87171;cursor:pointer;font-size:0.85rem;">🚫</button>
<div class="mockup-body" style="padding:14px;background:#0a1220;text-align:center;">
<img src="screenshots/zeiteinstellung-global.png" alt="Prompt: Standard-Redezeit für alle Mitglieder" style="max-width:460px;width:100%;display:inline-block;border-radius:8px;">
</div>
<!-- Normal -->
<div style="display:flex;align-items:center;gap:10px;padding:10px 12px;background:rgba(255,255,255,0.04);border:1px solid rgba(255,255,255,0.08);border-radius:10px;">
<span style="color:rgba(255,255,255,0.25);font-size:1rem;">⠿</span>
<div style="width:38px;height:38px;border-radius:50%;background:#1e3a5f;display:flex;align-items:center;justify-content:center;font-size:0.75rem;font-weight:700;color:white;flex-shrink:0;">SL</div>
<div style="flex:1;"><div style="font-size:0.85rem;font-weight:700;color:white;">Sandra Lang</div><div style="font-size:0.72rem;color:rgba(255,255,255,0.45);">Marketing</div></div>
<button style="background:rgba(255,255,255,0.08);border:none;border-radius:6px;padding:5px 8px;color:rgba(255,255,255,0.6);cursor:pointer;font-size:0.85rem;">↺</button>
<button style="background:rgba(255,255,255,0.05);border:none;border-radius:6px;padding:5px 8px;color:rgba(255,255,255,0.4);cursor:pointer;font-size:0.85rem;">🚫</button>
</div>
<p style="font-weight:700;font-size:0.85rem;margin:20px 0 8px;">B) Individuelle Zeit pro Mitglied</p>
<div class="steps">
<div class="step"><p>In der Mitgliederliste rechts neben jedem Namen erscheint ein kleines rot umrandetes Zeit-Feld.</p></div>
<div class="step"><p>Auf dieses Feld klicken und den abweichenden Wert eingeben (leer lassen = Standardzeit übernehmen).</p></div>
<div class="step"><p>Nützlich z. B. für neue Mitglieder mit längerer Vorstellung oder für Ehrengäste.</p></div>
</div>
<div class="mockup">
<div class="mockup-bar">
<div class="mockup-dot" style="background:#ff5f57;"></div>
<div class="mockup-dot" style="background:#febc2e;"></div>
<div class="mockup-dot" style="background:#28c840;"></div>
<span style="color:rgba(255,255,255,0.4);font-size:0.78rem;margin-left:8px;">Individuelles Zeit-Feld pro Mitglied</span>
</div>
<div class="mockup-body" style="padding:20px;background:#0a1220;text-align:center;">
<img src="screenshots/zeit-pro-mitglied.png" alt="Kleines Zeit-Feld neben dem Mitglied" style="width:90px;display:inline-block;border-radius:6px;background:white;padding:6px;">
</div>
<div style="margin-top:10px;font-size:0.75rem;color:rgba(255,255,255,0.35);">↺ = Vertretung eintragen &nbsp;·&nbsp; 🚫 = Als abwesend markieren</div>
</div>
</div>
</div>
@@ -359,22 +396,8 @@
<div class="mockup-dot" style="background:#28c840;"></div>
<span style="color:rgba(255,255,255,0.4);font-size:0.78rem;margin-left:8px;">Steuerung – Vertretung eintragen</span>
</div>
<div class="mockup-body">
<div class="mock-sub-modal">
<h4>Vertreter für Klaus Schmidt</h4>
<div style="font-size:0.72rem;color:rgba(255,255,255,0.4);margin-bottom:8px;">STAMMVERTRETER WÄHLEN</div>
<div class="mock-sv-card">
<div class="mock-avatar" style="background:#1a2744;width:32px;height:32px;">MF</div>
<div><div class="mock-sv-name">Max Fischer</div><div class="mock-sv-meta">Fischer GmbH · Versicherung</div></div>
</div>
<div class="mock-sv-card">
<div class="mock-avatar" style="background:#4a1942;width:32px;height:32px;">LB</div>
<div><div class="mock-sv-name">Lisa Berger</div><div class="mock-sv-meta">Berger &amp; Co · Marketing</div></div>
</div>
<div style="font-size:0.72rem;color:rgba(255,255,255,0.4);margin:10px 0 6px;">ODER MANUELL EINGEBEN</div>
<div class="mock-field">Name des Vertreters …</div>
<div class="mock-field">Firma …</div>
</div>
<div class="mockup-body" style="padding:14px;background:#0a1220;text-align:center;">
<img src="screenshots/vertreter-erfassen.png" alt="Modal: Vertretung für Mitglied erfassen" style="max-width:100%;display:inline-block;border-radius:8px;">
</div>
</div>
</div>
@@ -388,10 +411,38 @@
<div class="card">
<div class="steps">
<div class="step"><p>Tab <strong>„Besucher"</strong> öffnen.</p></div>
<div class="step"><p>Auf <strong>„+ Besucher hinzufügen"</strong> klicken.</p></div>
<div class="step"><p>Name und optional Firma eingeben und speichern.</p></div>
<div class="step"><p>Besucher erscheinen am Ende der Vorstellungsrunde nach allen Mitgliedern.</p></div>
<div class="step"><p>In der rechten Seitenleiste den Tab <strong>„Besucher"</strong> öffnen.</p></div>
<div class="step"><p>Name eingeben, optional Firma, Fachgebiet, „Eingeladen von" (Mitglied wählen) und Foto-URL ergänzen.</p></div>
<div class="step"><p>Auf <strong>„+ Besucher hinzufügen"</strong> klicken — der Besucher erscheint sofort in der Reihenfolge.</p></div>
<div class="step"><p>Besucher werden am Ende der Vorstellungsrunde nach allen Mitgliedern eingeblendet.</p></div>
</div>
</div>
<div class="mockup">
<div class="mockup-bar">
<div class="mockup-dot" style="background:#ff5f57;"></div>
<div class="mockup-dot" style="background:#febc2e;"></div>
<div class="mockup-dot" style="background:#28c840;"></div>
<span style="color:rgba(255,255,255,0.4);font-size:0.78rem;margin-left:8px;">Steuerung – Besucher hinzufügen</span>
</div>
<div class="mockup-body" style="padding:14px;background:#0a1220;text-align:center;">
<img src="screenshots/besucher-eintragen.png" alt="Formular: Besucher hinzufügen" style="max-width:320px;width:100%;display:inline-block;border-radius:8px;">
</div>
</div>
<div class="info">
<strong>Schnellerfassung per PDF:</strong> Wenn du eine Besucher-/Vertreterliste als PDF vorliegen hast (z. B. aus dem Chapter-Portal), klick oben in der Kopfzeile auf <strong>„📄 PDF importieren"</strong> und lege die PDF in das Feld — Einträge werden automatisch als Zeilen erkannt und du kannst sie vor dem Import noch anpassen.
</div>
<div class="mockup">
<div class="mockup-bar">
<div class="mockup-dot" style="background:#ff5f57;"></div>
<div class="mockup-dot" style="background:#febc2e;"></div>
<div class="mockup-dot" style="background:#28c840;"></div>
<span style="color:rgba(255,255,255,0.4);font-size:0.78rem;margin-left:8px;">Steuerung – Schnellerfassung per PDF</span>
</div>
<div class="mockup-body" style="padding:14px;background:#0a1220;text-align:center;">
<img src="screenshots/besucher-vertreterliste.png" alt="Modal: Besucher- und Vertreterliste per PDF importieren" style="max-width:100%;display:inline-block;border-radius:8px;">
</div>
</div>
@@ -408,7 +459,7 @@
</div>
<div class="info">
Das Admin-Panel öffnest du über <code>http://localhost:8181/admin.html</code> — am einfachsten über den Link im Steuerungs-Fenster unter dem Tab <strong>„Admin"</strong>.
Das Admin-Panel öffnest du am einfachsten über den Link im Steuerungs-Fenster unter dem Tab <strong>„Admin"</strong> (Button <strong>„⚙ Admin-Panel öffnen"</strong>) — das funktioniert unabhängig davon, wie das Tool gestartet wurde. Alternativ, falls das Tool über <strong>start.command</strong> (Terminal) gestartet wurde, ist es auch direkt unter <code>http://localhost:8181/admin.html</code> erreichbar — diese Adresse funktioniert <strong>nur</strong>, wenn das Tool auf diesem Weg läuft.
</div>
<div class="card">
@@ -422,37 +473,8 @@
</div>
</div>
<div class="admin-mockup">
<div class="admin-header">BNI Admin-Panel · BNI Chapter Sonne</div>
<div class="admin-tabs">
<div class="admin-tab">Stammvertreter</div>
<div class="admin-tab active">Mitglieder</div>
<div class="admin-tab">Einstellungen</div>
</div>
<div class="admin-body">
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;">
<span style="font-weight:700;font-size:0.9rem;">Mitglieder</span>
<div style="display:flex;gap:8px;">
<span style="background:#f3f4f6;border:1px solid var(--border);border-radius:6px;padding:5px 10px;font-size:0.78rem;font-weight:600;">🔄 Vom Server laden</span>
<span style="background:var(--red);color:white;border-radius:6px;padding:5px 10px;font-size:0.78rem;font-weight:600;">📤 Auf Server hochladen</span>
</div>
</div>
<div class="admin-member-row">
<div class="mock-avatar" style="background:#1a2744;width:40px;height:40px;font-size:0.8rem;">AM</div>
<div style="flex:1;"><div style="font-size:0.88rem;font-weight:600;">Anna Müller</div><div style="font-size:0.75rem;color:var(--muted);">Steuerberatung</div></div>
<span class="admin-photo-badge ok">✓ Foto</span>
</div>
<div class="admin-member-row">
<div class="mock-avatar" style="background:#4a1942;width:40px;height:40px;font-size:0.8rem;">KS</div>
<div style="flex:1;"><div style="font-size:0.88rem;font-weight:600;">Klaus Schmidt</div><div style="font-size:0.75rem;color:var(--muted);">IT-Systeme</div></div>
<span class="admin-photo-badge missing">+ Foto</span>
</div>
<div class="admin-member-row">
<div class="mock-avatar" style="background:#1e3a5f;width:40px;height:40px;font-size:0.8rem;">SL</div>
<div style="flex:1;"><div style="font-size:0.88rem;font-weight:600;">Sandra Lang</div><div style="font-size:0.75rem;color:var(--muted);">Marketing</div></div>
<span class="admin-photo-badge ok">✓ Foto</span>
</div>
</div>
<div class="admin-mockup" style="padding:0;">
<img src="screenshots/admin-panel-mitglieder.png" alt="Admin-Panel Mitglieder-Tab" style="width:100%;display:block;">
</div>
<div class="card" style="margin-top:16px;">
@@ -495,13 +517,18 @@
<li>Mitglieder vom Server laden</li>
<li>Fotos auf Server hochladen</li>
<li>Stammvertreter sichern</li>
<li>Agenda-Punkte mit Live-Einbettung anzeigen (Zoho Show)</li>
</ul>
</div>
</div>
</div>
<div class="highlight-box">
<strong>Empfehlung:</strong> Vor jedem Meeting einmal kurz „Vom Server laden" klicken — so hast du immer die aktuellste Mitgliederliste &amp; Fotos, auch wenn beim Meeting kein Internet verfügbar ist.
<strong>Empfehlung:</strong> Vor jedem Meeting einmal kurz <strong>„Vom Server laden"</strong> klicken — <em>vorausgesetzt</em>, die Liste wurde vorher aktualisiert und auf den Server hochgeladen. So sind Mitgliederliste &amp; Fotos auf dem aktuellen Stand, auch wenn beim Meeting kein Internet verfügbar ist.
</div>
<div class="tip">
<strong>Neue Mitglieder oder Änderungen?</strong> Wenn du keine Berechtigung zum Hochladen hast, gib die Änderungen an dein Support-Team weiter — dort werden die Mitgliederdaten angepasst und auf dem Server gespeichert. Beim nächsten „Vom Server laden" hast du die neue Version.
</div>
</div>
@@ -525,7 +552,7 @@
</div>
<div class="mockup-body">
<div style="background:#1a2744;color:white;padding:10px 14px;border-radius:8px;display:flex;align-items:center;gap:12px;font-size:0.85rem;">
<span>🆕 Update 1.2.0 verfügbar – Timer-Schalter im Admin-Menü</span>
<span>🆕 Update 1.5 verfügbar – Farbwarnung, Glockenton &amp; 8-Augen-Timer</span>
<button class="mock-btn-red" style="padding:4px 12px;font-size:0.82rem;white-space:nowrap;">Jetzt laden</button>
</div>
</div>
@@ -572,14 +599,8 @@
<div class="mockup-dot" style="background:#28c840;"></div>
<span style="color:rgba(255,255,255,0.4);font-size:0.78rem;margin-left:8px;">Steuerung – Admin-Tab</span>
</div>
<div class="mockup-body">
<div style="background:#1e2235;border-radius:10px;padding:14px;">
<div style="color:rgba(255,255,255,0.4);font-size:0.72rem;font-weight:700;text-transform:uppercase;letter-spacing:1px;margin-bottom:10px;">Einstellungen</div>
<label style="display:flex;align-items:center;gap:10px;cursor:pointer;font-size:0.85rem;color:white;">
<input type="checkbox" checked style="width:15px;height:15px;">
Zeitanzeige aktiv
</label>
</div>
<div class="mockup-body" style="padding:14px;background:#0a1220;text-align:center;">
<img src="screenshots/zeitanzeige-aktiv.png" alt="Admin-Sidebar mit Zeitanzeige-Checkbox" style="max-width:340px;width:100%;display:inline-block;border-radius:8px;">
</div>
</div>
@@ -588,6 +609,246 @@
</div>
</div>
<!-- ========== 12. 8-AUGEN-TIMER ========== -->
<div class="section" id="augen-timer">
<div class="section-header">
<div class="step-num">12</div>
<h2>8-Augen-Gespräche Timer</h2>
</div>
<div class="info">
Für 8-Augen-Gespräche gibt es einen eigenen Vollbild-Timer mit einer Uhr pro Tischgröße (3er / 4er / 5er / 6er). Am 4er-Tisch wird die gewünschte Sprechzeit eingegeben — die anderen Tische werden automatisch so berechnet, dass alle Redner die passende Zeit haben.
</div>
<div class="card">
<div class="steps">
<div class="step"><p>Im Steuerungs-Fenster den Tab <strong>„Admin"</strong> (rechte Seitenleiste) öffnen.</p></div>
<div class="step"><p>Im Abschnitt <strong>„8-Augen-Gespräche"</strong> auf <strong>„👥 8-Augen Timer starten"</strong> klicken — der Vollbild-Timer öffnet sich.</p></div>
<div class="step"><p>In der unteren Leiste unter <strong>„Wechsel 4er"</strong> die gewünschte Sprechzeit eingeben (z. B. <code>8:00</code> für 8 Minuten) und mit <strong>✓</strong> übernehmen.</p></div>
<div class="step"><p>Mit den Tischgrößen-Buttons (<strong>3er / 4er / 5er / 6er</strong>) auswählen, welche Timer angezeigt werden sollen — nicht benötigte einfach ausblenden.</p></div>
<div class="step"><p>Auf <strong>„▶ Start"</strong> klicken — alle sichtbaren Timer laufen gleichzeitig los.</p></div>
<div class="step"><p>Am Ende jeder Sprechzeit erklingt der Glockenton, danach folgt eine <strong>3 Sekunden Wechsel-Phase</strong> (blaue Karte, Countdown), bevor die nächste Sprechzeit startet.</p></div>
<div class="step"><p>Wenn alle Redner durch sind, stoppt der Timer automatisch — die Karten werden grün mit <strong>✓ Alle N Redner durch</strong>.</p></div>
<div class="step"><p>Mit <strong>„✕ Beenden"</strong> schließt sich der Vollbild-Timer und die App springt zurück in die Vorstellungsrunde.</p></div>
</div>
</div>
<div class="mockup">
<div class="mockup-bar">
<div class="mockup-dot" style="background:#ff5f57;"></div>
<div class="mockup-dot" style="background:#febc2e;"></div>
<div class="mockup-dot" style="background:#28c840;"></div>
<span style="color:rgba(255,255,255,0.4);font-size:0.78rem;margin-left:8px;">Anzeige – 8-Augen Timer (Vollbild)</span>
</div>
<div class="mockup-body" style="background:#0a1220;padding:0;">
<img src="screenshots/augen-timer.png" alt="8-Augen-Timer Vollbild" style="width:100%;display:block;">
</div>
</div>
<div class="highlight-box">
<strong>Farbwarnung:</strong> Timer-Karte wird <strong>gelb</strong> ab 30 s Restzeit und <strong>rot</strong> ab 10 s. Bei jedem Rednerwechsel und Rundenende ertönt zusätzlich ein Glockenton.
</div>
<div class="tip">
<strong>Rechenlogik:</strong> Die Rundendauer bleibt für alle Tische gleich (z. B. 8 min am 4er = 4 × 8 min = 32 min Runde). Der 3er-Tisch bekommt entsprechend 10:40 pro Redner, der 5er 6:24, der 6er 5:20. Die 3 Sekunden Wechsel hängen sich zusätzlich hinter jeden Redner (außer dem letzten).
</div>
</div>
<!-- ========== 13. MITGLIEDER SYNC ========== -->
<div class="section" id="mitglieder-sync">
<div class="section-header">
<div class="step-num">13</div>
<h2>Mitglieder mit BNI-Website synchronisieren</h2>
</div>
<div class="info">
Neue Mitglieder oder aktualisierte Fachgebiete/Fotos direkt aus der offiziellen BNI-Mitgliederliste in die App übernehmen. Läuft einmalig eingerichtet über zwei Bookmarklets im Browser.
</div>
<div class="card">
<p style="font-weight:700;font-size:0.9rem;margin-bottom:10px;">Ablauf</p>
<div class="steps">
<div class="step"><p>Im Steuerungs-Fenster oben in der Kopfzeile auf <strong>„🔄 Mitglieder aktualisieren"</strong> klicken.</p></div>
<div class="step"><p><strong>Schritt 1 (einmalig):</strong> Beide Bookmarklet-Buttons in die Lesezeichenleiste des Browsers ziehen. Zuerst <strong>„Diagnose"</strong> auf der BNI-Mitgliederliste ausführen und die heruntergeladene Diagnose-Datei hier hochladen — damit passt sich der Export-Button automatisch an die aktuelle Seitenstruktur an.</p></div>
<div class="step"><p><strong>Schritt 2:</strong> BNI-Mitgliederliste öffnen (Link im Dialog), warten bis alle Mitglieder geladen sind, dann Bookmarklet <strong>„BNI Mitglieder exportieren"</strong> klicken — es lädt automatisch eine JSON-Datei herunter.</p></div>
<div class="step"><p><strong>Schritt 3:</strong> Die JSON-Datei per <strong>„JSON-Datei laden &amp; synchronisieren"</strong> in der App einlesen. Bestehende Mitglieder werden aktualisiert (Foto, Fachgebiet), neue kommen dazu. Es wird niemand gelöscht.</p></div>
</div>
</div>
<div class="mockup">
<div class="mockup-bar">
<div class="mockup-dot" style="background:#ff5f57;"></div>
<div class="mockup-dot" style="background:#febc2e;"></div>
<div class="mockup-dot" style="background:#28c840;"></div>
<span style="color:rgba(255,255,255,0.4);font-size:0.78rem;margin-left:8px;">Dialog – Mitglieder synchronisieren</span>
</div>
<div class="mockup-body" style="padding:14px;background:#0a1220;text-align:center;">
<img src="screenshots/mitglieder-sync.png" alt="Modal: Mitglieder mit BNI-Website abgleichen" style="max-width:100%;display:inline-block;border-radius:8px;">
</div>
</div>
<div class="tip">
<strong>Hinweis:</strong> Nach dem Sync die neue Liste unbedingt über das Admin-Panel <strong>„Auf Server hochladen"</strong> — sonst haben andere Geräte die alten Daten. Ohne Upload-Berechtigung: Änderungen ans Support-Team melden.
</div>
</div>
<!-- ========== 14. IMPORT / EXPORT ========== -->
<div class="section" id="import-export">
<div class="section-header">
<div class="step-num">14</div>
<h2>Import / Export &amp; Backup</h2>
</div>
<div class="info">
Vollständiges Backup der Mitgliederdaten als JSON-Datei — nützlich für Umzüge zwischen Geräten, für einen sicheren Zwischenstand oder um lokale Kurzlinks &amp; Offline-Fotos (Profildaten) zu sichern.
</div>
<div class="card">
<p style="font-weight:700;font-size:0.9rem;margin-bottom:10px;">Mitgliederdaten (JSON)</p>
<div class="steps">
<div class="step"><p>Im Steuerungs-Fenster oben auf <strong>„⬇ Import / Export"</strong> klicken.</p></div>
<div class="step"><p><strong>„Exportieren"</strong> — die kompletten Mitgliederdaten werden als Text im Feld angezeigt (per Copy&amp;Paste sichern oder in eine Datei speichern).</p></div>
<div class="step"><p><strong>„Importieren"</strong> — vorher exportierten Text wieder einfügen und einlesen. Ersetzt die aktuellen Daten im Browser.</p></div>
</div>
<p style="font-weight:700;font-size:0.9rem;margin:20px 0 10px;">Profildaten (Kurzlinks &amp; Offline-Fotos)</p>
<div class="steps">
<div class="step"><p>Kurzlinks (z. B. Website-Weiterleitungen) und lokal hochgeladene Fotos werden <strong>getrennt</strong> gespeichert und bleiben bei einem Mitglieder-Sync erhalten.</p></div>
<div class="step"><p><strong>„⬇ profildaten.json speichern"</strong> — Datei sichern und im Projektordner ablegen.</p></div>
<div class="step"><p>Nach einem Browser-Reset oder auf einem neuen Gerät: <strong>„⬆ PROFILDATEN.JSON LADEN"</strong> — Kurzlinks &amp; Fotos sind wieder da.</p></div>
</div>
</div>
<div class="mockup">
<div class="mockup-bar">
<div class="mockup-dot" style="background:#ff5f57;"></div>
<div class="mockup-dot" style="background:#febc2e;"></div>
<div class="mockup-dot" style="background:#28c840;"></div>
<span style="color:rgba(255,255,255,0.4);font-size:0.78rem;margin-left:8px;">Dialog – Import / Export</span>
</div>
<div class="mockup-body" style="padding:14px;background:#0a1220;text-align:center;">
<img src="screenshots/import-export.png" alt="Modal: Import / Export" style="max-width:100%;display:inline-block;border-radius:8px;">
</div>
</div>
</div>
<!-- ========== 15. AGENDA-FOLIEN ========== -->
<div class="section" id="agenda">
<div class="section-header">
<div class="step-num">15</div>
<h2>Agenda-Folien für Online-Meetings (Hybrid-Chapter)</h2>
</div>
<div class="info">
Hybrid-Chapter (z. B. Lumora) treffen sich einmal im Monat vor Ort, sonst online. Für Online-Meetings läuft ein deutlich
größerer Ablauf als nur die Vorstellungsrunde — Begrüßung, Meeting-Regeln, DSGVO, BNI-Zahlen, Auszeichnungen, Events
usw. Diese Rahmen-Folien lassen sich direkt im Tool anlegen und an der passenden Stelle im Ablauf anzeigen — als
hochgeladenes Bild oder als Live-Einbettung aus Zoho Show.
</div>
<div class="card">
<p style="font-weight:700;font-size:0.9rem;margin-bottom:10px;">Punkte im Admin-Panel anlegen</p>
<div class="steps">
<div class="step"><p>Im Admin-Panel den Tab <strong>„Agenda"</strong> öffnen.</p></div>
<div class="step"><p>Auf <strong>„+ Agenda-Punkt hinzufügen"</strong> klicken (oder einen bestehenden Punkt anklicken, um ihn zu bearbeiten).</p></div>
<div class="step"><p>Eine <strong>Bezeichnung</strong> eingeben und die <strong>Anzeigeart</strong> wählen: „Bild" oder „Live-Einbettung".</p></div>
<div class="step"><p>Auf <strong>„Speichern"</strong> klicken — der Punkt erscheint in der Liste.</p></div>
</div>
</div>
<div class="admin-mockup" style="padding:0;">
<img src="screenshots/agenda-admin-liste.png" alt="Admin-Panel Agenda-Tab mit Liste der Punkte" style="width:100%;display:block;">
</div>
<p style="font-weight:700;font-size:0.85rem;margin:20px 0 8px;">A) Anzeigeart „Bild"</p>
<div class="card">
<p style="font-size:0.88rem;color:var(--muted);margin-bottom:0;">Für einen Folien-Export (z. B. aus PowerPoint oder Zoho Show als Bild exportiert). Über <strong>„Bild wählen"</strong> die Datei aus dem Finder wählen — sie wird automatisch auf eine für Vollbild-Anzeige passende Größe verkleinert, bevor sie hochgeladen wird.</p>
</div>
<div class="mockup">
<div class="mockup-bar">
<div class="mockup-dot" style="background:#ff5f57;"></div>
<div class="mockup-dot" style="background:#febc2e;"></div>
<div class="mockup-dot" style="background:#28c840;"></div>
<span style="color:rgba(255,255,255,0.4);font-size:0.78rem;margin-left:8px;">Admin-Panel – Agenda-Punkt bearbeiten (Bild)</span>
</div>
<div class="mockup-body" style="padding:14px;background:#0a1220;text-align:center;">
<img src="screenshots/agenda-punkt-bild.png" alt="Modal: Agenda-Punkt bearbeiten, Anzeigeart Bild" style="max-width:360px;width:100%;display:inline-block;border-radius:8px;">
</div>
</div>
<p style="font-weight:700;font-size:0.85rem;margin:20px 0 8px;">B) Anzeigeart „Live-Einbettung"</p>
<div class="card">
<p style="font-size:0.88rem;color:var(--muted);margin-bottom:0;">Für eine Folie, die das Team gemeinsam in Zoho Show pflegt — Änderungen sind sofort live, ohne erneuten Upload. In Zoho Show: <strong>Datei → Freigeben/Veröffentlichen → Einbetten</strong>, den dortigen Link in das Feld „Einbettungs-URL" einfügen. Am zuverlässigsten funktioniert das, wenn jeder Agenda-Punkt eine eigene, kleine Zoho-Show-Datei ist (statt einer großen Gesamt-Präsentation) — dann startet die Einbettung immer bei der ersten Folie.</p>
</div>
<div class="mockup">
<div class="mockup-bar">
<div class="mockup-dot" style="background:#ff5f57;"></div>
<div class="mockup-dot" style="background:#febc2e;"></div>
<div class="mockup-dot" style="background:#28c840;"></div>
<span style="color:rgba(255,255,255,0.4);font-size:0.78rem;margin-left:8px;">Admin-Panel – Agenda-Punkt bearbeiten (Live-Einbettung)</span>
</div>
<div class="mockup-body" style="padding:14px;background:#0a1220;text-align:center;">
<img src="screenshots/agenda-punkt-embed.png" alt="Modal: Agenda-Punkt bearbeiten, Anzeigeart Live-Einbettung" style="max-width:360px;width:100%;display:inline-block;border-radius:8px;">
</div>
</div>
<div class="tip">
<strong>Nicht vergessen:</strong> Nach dem Anlegen/Ändern von Punkten im Admin-Panel oben rechts auf <strong>„📤 Auf Server hochladen"</strong> klicken — sonst kommen die Änderungen nicht im Steuerpult (bzw. auf anderen Geräten) an.
</div>
<div class="card" style="margin-top:24px;">
<p style="font-weight:700;font-size:0.9rem;margin-bottom:10px;">Reihenfolge festlegen und live anzeigen</p>
<div class="steps">
<div class="step"><p>Im Steuerpult den neuen Tab <strong>„Agenda"</strong> öffnen (ganz links, neben „Mitglieder" und „Besucher").</p></div>
<div class="step"><p>Punkte per <strong>Drag &amp; Drop</strong> in die gewünschte Reihenfolge bringen — genau wie bei der Mitgliederliste.</p></div>
<div class="step"><p>Auf <strong>„▶ Anzeigen"</strong> klicken, um einen Punkt sofort auf dem Display zu zeigen.</p></div>
<div class="step"><p>Mit dem <strong>🚫-Button</strong> lässt sich ein Punkt aus der aktiven Reihenfolge ausblenden (für dieses Meeting nicht gebraucht) — er taucht dann unten unter „Ausgeblendet" auf und kann dort per <strong>„+ Einblenden"</strong> jederzeit wieder aktiviert werden.</p></div>
</div>
</div>
<div class="mockup">
<div class="mockup-bar">
<div class="mockup-dot" style="background:#ff5f57;"></div>
<div class="mockup-dot" style="background:#febc2e;"></div>
<div class="mockup-dot" style="background:#28c840;"></div>
<span style="color:rgba(255,255,255,0.4);font-size:0.78rem;margin-left:8px;">Steuerpult – Agenda-Tab</span>
</div>
<div class="mockup-body" style="padding:0;background:#0a1220;">
<img src="screenshots/agenda-steuerung.png" alt="Steuerpult mit Agenda-Tab und sortierbarer Reihenfolge" style="width:100%;display:block;">
</div>
</div>
<div class="highlight-box">
<strong>Mitglieder-, Besucher- und Marketing-/Ergebnisrunde sind eingebaute Agenda-Punkte:</strong> Sie lassen sich genau wie die Bild-/Einbettungs-Folien frei in die Reihenfolge einsortieren — z. B. Begrüßung → Regeln → <em>Mitglieder-Vorstellungsrunde</em> → Auszeichnung → <em>Besucher-Vorstellungsrunde</em> → Events.
</div>
<div class="card">
<p style="font-weight:700;font-size:0.9rem;margin-bottom:10px;">Marketing-/Ergebnisrunde</p>
<p style="font-size:0.88rem;color:var(--muted);">Läuft dieselbe Mitgliederliste noch einmal in derselben Reihenfolge durch wie die Vorstellungsrunde — aber ohne Redezeit-Timer. Gedacht für die Runde, in der jedes Mitglied kurz berichtet, was es in der vergangenen Woche für andere Mitglieder getan hat (Empfehlungen, Besucher, 4-Augen-Gespräche, Trainings, Umsatzdank).</p>
</div>
<div class="card">
<p style="font-weight:700;font-size:0.9rem;margin-bottom:10px;">„Weiter"-Button folgt der Agenda</p>
<p style="font-size:0.88rem;color:var(--muted);">Der rote „Weiter"-Button oben führt automatisch zum jeweils nächsten Punkt in der festgelegten Reihenfolge — egal ob als Nächstes eine Folie, die Mitglieder-Vorstellungsrunde oder die Besucherrunde kommt. Bei einer Live-Einbettung kann „Weiter" nicht innerhalb der eingebetteten Folie selbst blättern (das bleibt Sache von Zoho Show), sondern springt direkt zum nächsten Agenda-Punkt.</p>
</div>
<div class="mockup">
<div class="mockup-bar">
<div class="mockup-dot" style="background:#ff5f57;"></div>
<div class="mockup-dot" style="background:#febc2e;"></div>
<div class="mockup-dot" style="background:#28c840;"></div>
<span style="color:rgba(255,255,255,0.4);font-size:0.78rem;margin-left:8px;">Display-Ansicht – laufende Agenda-Folie</span>
</div>
<div class="mockup-body" style="padding:0;background:#0a1220;">
<img src="screenshots/agenda-display.png" alt="Display-Ansicht mit einer live eingebetteten Agenda-Folie" style="width:100%;display:block;">
</div>
</div>
<div class="tip">
<strong>Bild wird nicht angezeigt?</strong> Meist liegt es daran, dass der Bild-Upload noch nicht abgeschlossen war, als „Speichern" geklickt wurde — einfach das Bild im Admin-Panel erneut auswählen und speichern. Erscheint stattdessen eine eingebettete Live-Folie nicht: in Zoho Show prüfen, ob die Datei über „Veröffentlichen" freigegeben ist, und im Browser testweise Werbeblocker/Privacy-Erweiterungen deaktivieren.
</div>
</div>
<!-- FOOTER -->
<div style="text-align:center;padding:32px 0;color:var(--muted);font-size:0.8rem;border-top:1px solid var(--border);margin-top:32px;">
BNI Vorstellungsrunde · Interne Anleitung · Bei Fragen an den Administrator wenden

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 661 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

BIN
screenshots/augen-timer.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 454 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 564 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 317 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -1,4 +1,4 @@
{
"version": "1.5",
"notes": "Zeitanzeige oben ergänzt. letzte 15 Sekunden gelber Hintergrund, letzte 5 Sekunden roter Hintergrund"
}
"version": "2.0",
"notes": "Agenda-Folien für Online-Meetings (Hybrid-Chapter): Bild- oder Live-Einbettungs-Folien frei in die Reihenfolge einsortieren, inkl. Mitglieder-/Besucher-Vorstellungsrunde und neuer Marketing-/Ergebnisrunde (ohne Timer). \"Weiter\" folgt jetzt der Agenda."
}