Feature: Foto-Upload für Mitglieder im Admin-Panel
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
84
admin.html
84
admin.html
@@ -214,6 +214,29 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Member Photo Modal -->
|
||||
<div class="modal-overlay" id="modal-member-photo">
|
||||
<div class="modal">
|
||||
<div class="modal-header">
|
||||
<div class="modal-title" id="member-photo-modal-title">Foto bearbeiten</div>
|
||||
<button class="modal-close" onclick="closeAdminModal('modal-member-photo')">✕</button>
|
||||
</div>
|
||||
<input type="hidden" id="member-photo-name">
|
||||
<div style="display:flex;align-items:center;gap:16px;margin:16px 0;">
|
||||
<img id="member-photo-thumb" class="photo-thumb" style="width:80px;height:80px;display:none;" src="" alt="">
|
||||
<div id="member-photo-initials" style="width:80px;height:80px;border-radius:50%;display:flex;align-items:center;justify-content:center;color:white;font-size:1.4rem;font-weight:700;flex-shrink:0;"></div>
|
||||
<div class="photo-actions" style="flex-direction:column;align-items:flex-start;">
|
||||
<label class="btn-file-label">📁 Foto wählen<input type="file" id="member-photo-file" accept="image/*" style="display:none" onchange="handleMemberPhotoFile(this)"></label>
|
||||
<button class="btn btn-danger btn-sm" id="member-photo-remove" onclick="removeMemberPhoto()" style="display:none;margin-top:6px;">✕ Foto entfernen</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-ghost" onclick="closeAdminModal('modal-member-photo')">Abbrechen</button>
|
||||
<button class="btn btn-primary" onclick="saveMemberPhoto()">Speichern</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Import from Chapter Modal -->
|
||||
<div class="modal-overlay" id="modal-import-chapter">
|
||||
<div class="modal">
|
||||
@@ -569,16 +592,75 @@ function renderMembersList() {
|
||||
const photoB64 = ex.photoB64 || ex.offlinePhotoB64 || null;
|
||||
const div = document.createElement('div');
|
||||
div.className = 'member-item';
|
||||
div.style.cursor = 'pointer';
|
||||
div.title = 'Foto bearbeiten';
|
||||
div.innerHTML = `${avatarHtml(m.name, photoB64, m.photoUrl, 40)}
|
||||
<div style="flex:1;min-width:0;">
|
||||
<div style="font-weight:600;font-size:0.88rem;">${escHtml(m.name)}</div>
|
||||
<div style="font-size:0.75rem;color:var(--muted);">${escHtml(m.company||'')}${m.specialty?' · '+escHtml(m.specialty):''}</div>
|
||||
</div>
|
||||
<span style="font-size:0.72rem;color:${photoB64?'var(--success)':'var(--muted)'};">${photoB64?'✓ Foto':'kein Foto'}</span>`;
|
||||
<span style="font-size:0.72rem;color:${photoB64?'var(--success)':'#d97706'};">${photoB64?'✓ Foto':'+ Foto'}</span>`;
|
||||
div.onclick = () => openMemberPhotoModal(m.name, photoB64);
|
||||
container.appendChild(div);
|
||||
});
|
||||
}
|
||||
|
||||
let _memberPhotoB64 = null;
|
||||
|
||||
function openMemberPhotoModal(name, currentPhotoB64) {
|
||||
_memberPhotoB64 = currentPhotoB64 || null;
|
||||
document.getElementById('member-photo-name').value = name;
|
||||
document.getElementById('member-photo-modal-title').textContent = name;
|
||||
updateMemberPhotoUI(_memberPhotoB64, name);
|
||||
openAdminModal('modal-member-photo');
|
||||
}
|
||||
|
||||
function updateMemberPhotoUI(b64, name) {
|
||||
_memberPhotoB64 = b64;
|
||||
const thumb = document.getElementById('member-photo-thumb');
|
||||
const initials = document.getElementById('member-photo-initials');
|
||||
const removeBtn = document.getElementById('member-photo-remove');
|
||||
if (b64) {
|
||||
thumb.src = b64; thumb.style.display = 'block';
|
||||
initials.style.display = 'none';
|
||||
removeBtn.style.display = 'inline-flex';
|
||||
} else {
|
||||
thumb.src = ''; thumb.style.display = 'none';
|
||||
initials.style.display = 'flex';
|
||||
initials.style.background = getColor(name || '');
|
||||
initials.textContent = getInitials(name || '');
|
||||
removeBtn.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
function handleMemberPhotoFile(input) {
|
||||
const file = input.files && input.files[0];
|
||||
if (!file) return;
|
||||
const name = document.getElementById('member-photo-name').value;
|
||||
resizePhotoToBase64(file).then(b64 => updateMemberPhotoUI(b64, name)).catch(e => alert(e.message));
|
||||
input.value = '';
|
||||
}
|
||||
|
||||
function removeMemberPhoto() {
|
||||
updateMemberPhotoUI(null, document.getElementById('member-photo-name').value);
|
||||
}
|
||||
|
||||
function saveMemberPhoto() {
|
||||
const name = document.getElementById('member-photo-name').value;
|
||||
const extras = loadExtras();
|
||||
const key = extrasKey(name);
|
||||
if (!extras[key]) extras[key] = {};
|
||||
if (_memberPhotoB64) {
|
||||
extras[key].photoB64 = _memberPhotoB64;
|
||||
} else {
|
||||
delete extras[key].photoB64;
|
||||
delete extras[key].offlinePhotoB64;
|
||||
}
|
||||
saveExtras(extras);
|
||||
closeAdminModal('modal-member-photo');
|
||||
renderMembersList();
|
||||
}
|
||||
|
||||
async function fetchMembersAdmin() {
|
||||
const statusEl = document.getElementById('members-status');
|
||||
statusEl.textContent = 'Lade vom Server…'; statusEl.style.color = 'var(--muted)';
|
||||
|
||||
Reference in New Issue
Block a user