/* ============================================================ BAN YARO — Partner-Profil-Editor Nur für User mit is_partner=1. ============================================================ */ window.Page_partner_profil = (() => { let _container = null; let _profile = null; async function init(container, appState) { _container = container; _render(); await _load(); } function refresh() { _load(); } function onDogChange() {} function _render() { _container.innerHTML = `

Mein Partner-Profil

Richte deine öffentliche Präsenz auf der Partner-Seite ein. Nach dem Absenden prüfen wir dein Profil und schalten es frei.

Lade…
`; } let _qrBatches = []; async function _load() { const el = _container.querySelector('#pp-content'); try { const d = await API.get('/partner/my-profile'); _profile = d.profile || {}; _profile._storage_mb = d.storage_mb || 0; _profile._storage_limit_mb = d.storage_limit_mb || 200; _qrBatches = (await API.get('/partner/my-qr').catch(() => [])) || []; el.innerHTML = _renderEditor(); _bindEvents(el); } catch (e) { el.innerHTML = `

${e.message}

`; } } function _statusBadge() { if (!_profile?.submitted_at && !_profile?.approved) return ''; const a = _profile.approved; if (a === 1) return `✓ Freigegeben`; if (a === -1) return `✗ Abgelehnt`; if (_profile.submitted_at) return `⏳ In Prüfung`; return `Entwurf`; } function _renderEditor() { const p = _profile || {}; const photos = p.photos || []; return `
Status: ${_statusBadge() || 'Noch kein Profil angelegt'}
Logo
${p.logo_url ? `` : ``}
PNG, JPG oder WebP · max. 5 MB · wird quadratisch zugeschnitten
Texte
Fotos & Videos (max. 6)
JPG, PNG, HEIC, MP4, MOV · max. 200 MB pro Datei
${_storageBar(p._storage_mb || 0, p._storage_limit_mb || 200)}
${photos.map((url, i) => { const isVid = url.endsWith('.mp4') || url.endsWith('.webm'); return `
${isVid ? `
▶ Video
` : ``}
`; }).join('')} ${photos.length < 6 ? ` ` : ''}
${_qrBatches.length ? `
Meine QR-Codes

Deine gedruckten QR-Codes (Sticker, Flyer). Jeder Scan und jede Registrierung darüber wird gezählt — so siehst du, was wo funktioniert.

${_qrBatches.map(b => `
${UI.escape(b.label)}
${b.quantity} Codes · ${(b.created_at || '').slice(0, 10)}
${b.scans}
Scans
${b.registrations}${b.attempts ? ` +${b.attempts}` : ''}
Registr.
${UI.icon('file-pdf')} PDF
`).join('')}
` : ''}
`; } function _bindEvents(el) { // Logo hochladen el.querySelector('#pp-logo-input')?.addEventListener('change', async e => { const file = e.target.files[0]; if (!file) return; const fd = new FormData(); fd.append('file', file); try { const r = await API.upload('/partner/my-profile/logo', fd); el.querySelector('#pp-logo-preview').innerHTML = ``; _profile = { ..._profile, logo_url: r.logo_url }; UI.toast.success('Logo gespeichert.'); } catch (err) { UI.toast.error(err.message); } }); // Texte speichern el.querySelector('#pp-text-form')?.addEventListener('submit', async e => { e.preventDefault(); const btn = e.target.querySelector('[type="submit"]'); const fd = UI.formData(e.target); await UI.asyncButton(btn, async () => { await API.put('/partner/my-profile', fd); _profile = { ..._profile, ...fd }; UI.toast.success('Gespeichert.'); }); }); // Foto/Video hochladen el.querySelector('#pp-photo-input')?.addEventListener('change', async e => { const file = e.target.files[0]; if (!file) return; const isVideo = file.type.startsWith('video/'); const fd = new FormData(); fd.append('file', file); if (isVideo) UI.toast.info('Video wird hochgeladen und komprimiert – das kann 1–2 Minuten dauern …', 120_000); try { const r = await API.upload('/partner/my-profile/photos', fd); _profile = { ..._profile, photos: r.photos }; await _load(); UI.toast.success(isVideo ? 'Video hinzugefügt.' : 'Foto hinzugefügt.'); } catch (err) { UI.toast.error(err.message); } }); // Foto löschen el.querySelectorAll('.pp-photo-del').forEach(btn => { btn.addEventListener('click', async () => { const idx = parseInt(btn.dataset.idx); try { const r = await API.post(`/partner/my-profile/photos/${idx}/delete`, {}); _profile = { ..._profile, photos: r.photos }; await _load(); } catch (err) { UI.toast.error(err.message); } }); }); // Einreichen el.querySelector('#pp-submit-btn')?.addEventListener('click', async () => { const btn = el.querySelector('#pp-submit-btn'); await UI.asyncButton(btn, async () => { await API.post('/partner/my-profile/submit', {}); UI.toast.success('Eingereicht! Wir prüfen dein Profil und schalten es bald frei.'); await _load(); }); }); } function _storageBar(usedMb, limitMb) { const pct = Math.min(100, Math.round((usedMb / limitMb) * 100)); const color = pct > 85 ? '#dc2626' : pct > 60 ? '#f59e0b' : '#22c55e'; return `
${usedMb.toFixed(1)} / ${limitMb} MB
`; } return { init, refresh, onDogChange }; })();