diff --git a/index.html b/index.html index ef414a9..92296a0 100644 --- a/index.html +++ b/index.html @@ -1668,6 +1668,7 @@ // ============================================================ const APP_VERSION = '1.1.0'; const GITEA_RAW = 'http://72.60.134.73:3000/api/v1/repos/cheubaum/BNI-Sonne/raw'; +const GITEA_API = 'http://72.60.134.73:3000/api/v1/repos/cheubaum/BNI-Sonne'; function giteaUrl(path) { return `${GITEA_RAW}/${path}?ref=main`; } const CHAPTER_CONFIG_KEY = 'bni-active-chapter'; @@ -4159,11 +4160,19 @@ async function fetchChapterMembersFromGitea() { if (!res.ok) return; const data = await res.json(); if (!data.members || !data.members.length) return; + const extras = loadExtras(); const mergedMap = new Map(state.members.map(m => [m.id, m])); data.members.forEach(m => { const ex = mergedMap.get(m.id); mergedMap.set(m.id, ex ? Object.assign({}, ex, m) : m); + // Embed photoData into extras so existing photo display picks it up + if (m.photoData) { + const key = extrasKey(m.name); + if (!extras[key]) extras[key] = {}; + extras[key].offlinePhotoB64 = m.photoData; + } }); + saveExtras(extras); state.members = Array.from(mergedMap.values()); const knownIds = new Set(state.meetingOrder); state.members.forEach(m => { if (!knownIds.has(m.id)) state.meetingOrder.push(m.id); }); @@ -4175,6 +4184,65 @@ async function fetchChapterMembersFromGitea() { } catch(e) { /* ignore */ } } +function buildMembersJson() { + const extras = loadExtras(); + const members = state.members.map(m => { + const ex = extras[extrasKey(m.name)] || {}; + const entry = { id: m.id, name: m.name, company: m.company, specialty: m.specialty, photoUrl: m.photoUrl || '', profileUrl: m.profileUrl || '' }; + if (ex.offlinePhotoB64) entry.photoData = ex.offlinePhotoB64; + return entry; + }); + return { lastUpdated: new Date().toISOString().slice(0, 10), members }; +} + +function saveAdminToken() { + const val = (document.getElementById('admin-token-input').value || '').trim(); + if (val) localStorage.setItem('bni-gitea-admin-token', val); + else localStorage.removeItem('bni-gitea-admin-token'); + renderAdminPanel(); +} + +async function uploadMembersToGitea() { + const token = localStorage.getItem('bni-gitea-admin-token'); + if (!token) { alert('Bitte zuerst den Admin-Token speichern.'); return; } + const statusEl = document.getElementById('upload-status'); + statusEl.textContent = 'Lädt hoch…'; + statusEl.style.color = 'var(--muted)'; + + const data = buildMembersJson(); + const jsonStr = JSON.stringify(data, null, 2); + const content = btoa(unescape(encodeURIComponent(jsonStr))); + const path = `chapters/${activeChapter.code}/members.json`; + + try { + // Get current SHA + let sha = null; + const shaRes = await fetch(`${GITEA_API}/contents/${path}`, { headers: { 'Authorization': `token ${token}` } }); + if (shaRes.ok) sha = (await shaRes.json()).sha; + + const body = { message: `Mitglieder aktualisiert ${new Date().toLocaleDateString('de')}`, content }; + if (sha) body.sha = sha; + + const res = await fetch(`${GITEA_API}/contents/${path}`, { + method: sha ? 'PUT' : 'POST', + headers: { 'Authorization': `token ${token}`, 'Content-Type': 'application/json' }, + body: JSON.stringify(body) + }); + if (res.ok) { + activeChapter.lastMemberUpload = new Date().toISOString(); + saveChapterConfig(activeChapter); + statusEl.textContent = `✓ ${data.members.length} Mitglieder hochgeladen`; + statusEl.style.color = 'var(--success)'; + } else { + statusEl.textContent = 'Fehler beim Upload. Token prüfen.'; + statusEl.style.color = '#dc2626'; + } + } catch(e) { + statusEl.textContent = 'Verbindungsfehler.'; + statusEl.style.color = '#dc2626'; + } +} + function renderAdminPanel() { const panel = document.getElementById('admin-panel'); if (!panel) return; @@ -4182,7 +4250,8 @@ function renderAdminPanel() { const code = activeChapter && activeChapter.code; const lastChecked = activeChapter && activeChapter.lastChecked ? new Date(activeChapter.lastChecked).toLocaleString('de') : '—'; const lastSync = activeChapter && activeChapter.lastMemberSync ? new Date(activeChapter.lastMemberSync).toLocaleString('de') : '—'; - const maskedCode = code ? code.slice(0, -3).replace(/./g, '·') + code.slice(-3) : '—'; + const lastUpload = activeChapter && activeChapter.lastMemberUpload ? new Date(activeChapter.lastMemberUpload).toLocaleString('de') : '—'; + const hasToken = !!localStorage.getItem('bni-gitea-admin-token'); panel.innerHTML = `