/** * pc-live | Adressbuch App * Kontakte verwalten, an Mail-App weitergeben, Kontaktkarte per Mail senden. */ const AddressBookApp = (() => { const WIN_ID = 'app-addressbook'; let _contacts = []; let _active = null; // contact id let _editing = false; let _editData = null; /* ── Helpers ──────────────────────────────────────────── */ function esc(s) { return String(s || '').replace(/&/g,'&').replace(//g,'>'); } function fmtDate(d) { if (!d) return ''; const dt = new Date(d); return isNaN(dt) ? '' : dt.toLocaleDateString('de-DE'); } function initials(name) { return (name || '?').split(' ').map(p => p[0] || '').slice(0,2).join('').toUpperCase(); } function avatarColor(name) { const colors = ['#3b82f6','#8b5cf6','#ec4899','#f59e0b','#10b981','#06b6d4','#ef4444']; let h = 0; for (const c of (name||'?')) h = (h * 31 + c.charCodeAt(0)) & 0xffffffff; return colors[Math.abs(h) % colors.length]; } /* ── Sidebar list ─────────────────────────────────────── */ function renderList() { if (!_contacts.length) return `
👤

Keine Kontakte

`; return `
` + _contacts.map(c => `
${esc(initials(c.name))}
${esc(c.name)}
${c.email ? `
${esc(c.email)}
` : ''} ${c.phone ? `
${esc(c.phone)}
` : ''}
`).join('') + `
`; } /* ── Detail / Edit ────────────────────────────────────── */ function renderDetail() { if (_editing) { const d = _editData || {}; return `

${d.id ? '✏ Kontakt bearbeiten' : '➕ Neuer Kontakt'}

`; } const c = _contacts.find(x => x.id === _active); if (!c) return `
👤

Kontakt auswählen

`; const bg = avatarColor(c.name); return `
${esc(initials(c.name))}
${esc(c.name)}
Hinzugefügt: ${fmtDate(c.created_at)}
${c.email ? `
✉ E-Mail / ID ${esc(c.email)}
` : ''} ${c.phone ? `
📞 Telefon ${esc(c.phone)}
` : ''} ${c.notes ? `
📝 Notizen ${esc(c.notes)}
` : ''}
${c.email ? ` ` : ''}
`; } /* ── Full refresh ─────────────────────────────────────── */ function _refresh() { const body = WindowManager.getBody(WIN_ID); if (!body) return; // Push contacts into mail app for autocomplete MailApp.setContacts(_contacts); body.innerHTML = `
${renderList()}
${renderDetail()}
`; } /* ── Actions ──────────────────────────────────────────── */ function _select(id) { _active = id; _editing = false; _editData = null; _refresh(); } function _startEdit(id) { _editing = true; _editData = id ? { ...(_contacts.find(c => c.id === id) || {}) } : {}; _active = id; _refresh(); } function _cancelEdit() { _editing = false; _editData = null; _refresh(); } function _save() { const name = document.getElementById('ab-name')?.value.trim(); const email = document.getElementById('ab-email')?.value.trim(); const phone = document.getElementById('ab-phone')?.value.trim(); const notes = document.getElementById('ab-notes')?.value.trim(); const status = document.getElementById('ab-status'); if (!name) { if (status) status.textContent = 'Name ist Pflichtfeld.'; return; } const payload = { name, email, phone, notes }; if (_editData && _editData.id) { fetchNui('updateContact', { id: _editData.id, ...payload }); } else { fetchNui('addContact', payload); } _editing = false; _editData = null; } function _delete(id) { // Kein confirm(): FiveMs CEF hat keinen Handler für die eingebauten // JS-Dialoge – der Aufruf öffnet nichts und lässt das NUI stehen. ICWebRender.confirmBox('Kontakt löschen', 'Kontakt wirklich löschen?', () => fetchNui('deleteContact', { id }), { danger: true, okLabel: 'Löschen' }); } function _mailTo(emailOrId) { // Open mail app in compose mode with prefilled To MailApp.open(); setTimeout(() => { MailApp._setView('compose'); setTimeout(() => { const t = document.getElementById('mail-to'); if (t) { t.value = emailOrId; t.focus(); } }, 50); }, 50); } function _forwardContact(id) { const c = _contacts.find(x => x.id === id); if (!c) return; const body = [ `── Kontaktkarte ──`, `Name: ${c.name}`, c.email ? `E-Mail: ${c.email}` : null, c.phone ? `Telefon: ${c.phone}` : null, c.notes ? `Notizen: ${c.notes}` : null, ].filter(Boolean).join('\n'); MailApp.open(); setTimeout(() => { MailApp._setView('compose'); setTimeout(() => { const s = document.getElementById('mail-subject'); const b = document.getElementById('mail-body'); if (s) s.value = `Kontakt: ${c.name}`; if (b) b.value = body; document.getElementById('mail-to')?.focus(); }, 50); }, 50); } /* ── Called from MailApp ("Als Kontakt speichern") ─────── */ function openAddNew(prefill) { open(); setTimeout(() => { _editing = true; _editData = prefill || {}; _active = null; _refresh(); }, 100); } /* ── NUI events ───────────────────────────────────────── */ function onContactsData(rows) { _contacts = rows || []; MailApp.setContacts(_contacts); if (WindowManager.getBody(WIN_ID)) _refresh(); } function onContactAdded(c) { _contacts.push(c); _contacts.sort((a,b) => a.name.localeCompare(b.name)); _active = c.id; _editing = false; MailApp.setContacts(_contacts); _refresh(); } function onContactUpdated(c) { const idx = _contacts.findIndex(x => x.id === c.id); if (idx !== -1) _contacts[idx] = c; else _contacts.push(c); _contacts.sort((a,b) => a.name.localeCompare(b.name)); _active = c.id; _editing = false; MailApp.setContacts(_contacts); _refresh(); } function onContactDeleted(id) { _contacts = _contacts.filter(c => c.id !== id); if (_active === id) _active = null; MailApp.setContacts(_contacts); _refresh(); } /* ── Open window ──────────────────────────────────────── */ function open() { const created = WindowManager.create({ id: WIN_ID, title: 'Adressbuch', icon: '👤', width: 720, height: 500, content: '', }); if (created) { _active = null; _editing = false; fetchNui('getContacts', {}); _refresh(); } } return { open, openAddNew, _select, _startEdit, _cancelEdit, _save, _delete, _mailTo, _forwardContact, onContactsData, onContactAdded, onContactUpdated, onContactDeleted, }; })();