/* global React, MZ */ const { useState, useEffect } = React; const ROLE_PL = { admin: 'administrator', moderator: 'moderator', trusted: 'zaufany', member: 'użytkownik' }; function Account({ userId, setRoute, profile: myProfile, onToast }) { const [u, setU] = useState(null); const [videos, setVideos] = useState([]); const [tab, setTab] = useState('videos'); const [loading, setLoading] = useState(true); const isMe = myProfile?.id === userId; useEffect(() => { (async () => { setLoading(true); try { const [prof, vids] = await Promise.all([ MZ.getProfile(userId), MZ.listUserVideos(userId), ]); setU(prof); setVideos(vids); } catch (e) { onToast('Nie znaleziono użytkownika'); } setLoading(false); })(); }, [userId]); if (loading || !u) return

Ładowanie profilu…

; const publishedVideos = videos.filter(v => v.status === 'published'); const totalVotes = publishedVideos.reduce((s, v) => s + (v.up||0) - (v.down||0), 0); const totalViews = publishedVideos.reduce((s, v) => s + (v.views||0), 0); return (
{ e.preventDefault(); setRoute({name:'home'}); }}>START / PROFIL / @{u.handle.toUpperCase()}
{isMe && } {isMe && }
{tab === 'videos' && ( publishedVideos.length > 0 ? (
{publishedVideos.map(v => setRoute({name:'video', id})} />)}
) :

Brak opublikowanych nagrań.

)} {tab === 'pending' && isMe && (
{videos.filter(v=>v.status!=='published').length === 0 ?

Brak oczekujących nagrań.

: videos.filter(v=>v.status!=='published').map(v => (
{v.title}
{v.city || '—'} · {timeAgo(v.created_at)}
{v.status==='pending'?'moderacja':v.status==='rejected'?'odrzucone':'usunięte'}
)) }
)} {tab === 'settings' && isMe && }
); } function AccountSettings({ profile, setU, onToast }) { const [name, setName] = useState(profile.name || ''); const [busy, setBusy] = useState(false); const save = async (e) => { e.preventDefault(); setBusy(true); try { await MZ.updateProfile({ name }); setU({ ...profile, name }); onToast('Profil zapisany'); } catch (er) { onToast(er.message); } setBusy(false); }; const logoutAll = async () => { if (!confirm('Wylogować ze wszystkich urządzeń?')) return; await MZ.signOut(); location.reload(); }; return (
setName(e.target.value)} />
NAZWY NIE MOŻNA ZMIENIĆ
Twoje dane

Zgodnie z RODO masz prawo do dostępu, sprostowania, usunięcia i przeniesienia swoich danych. Skontaktuj się z nami: kontakt@miejscezdarzenia.pl

); } function Admin({ setRoute, onToast }) { const [section, setSection] = useState('overview'); const [counts, setCounts] = useState({ videos: 0, queue: 0, reports: 0, users: 0 }); useEffect(() => { MZ.stats().then(setCounts); }, [section]); const sections = [ { id:'overview', label:'Przegląd' }, { id:'queue', label:'Kolejka moderacji', count: counts.queue }, { id:'videos', label:'Wszystkie nagrania', count: counts.videos }, { id:'reports', label:'Zgłoszenia', count: counts.reports }, { id:'users', label:'Użytkownicy', count: counts.users }, ]; return (
{section === 'overview' && } {section === 'queue' && } {section === 'videos' && } {section === 'reports' && } {section === 'users' && }
); } function AdminOverview({ counts }) { return (
Admin

Przegląd

Opublikowane
{counts.videos}
W kolejce
{counts.queue}
Otwarte zgłoszenia
{counts.reports}
Użytkownicy
{counts.users}
); } function AdminQueue({ onToast }) { const [items, setItems] = useState([]); const [loading, setLoading] = useState(true); const load = async () => { setLoading(true); setItems(await MZ.adminListQueue()); setLoading(false); }; useEffect(() => { load(); }, []); const act = async (id, status) => { try { await MZ.adminSetStatus(id, status); onToast(status==='published'?'Zatwierdzone':'Odrzucone'); load(); } catch(e){ onToast(e.message); } }; return (
Moderacja

Kolejka ({items.length})

{loading ? : items.length === 0 ? : items.map(q => ( )) }
TytułAutorMiastoDodanoYTAkcje
Ładowanie…
Kolejka pusta.
{q.title} @{q.author_profile?.handle || '—'} {q.city || '—'} {fmtDate(q.created_at)} {q.youtube_id}
); } function AdminVideos({ setRoute, onToast }) { const [items, setItems] = useState([]); const [sev, setSev] = useState('all'); const load = async () => setItems(await MZ.listVideos({ status:'published', limit:500 })); useEffect(() => { load(); }, []); const list = sev === 'all' ? items : items.filter(v => v.severity === sev); const remove = async (id) => { if (!confirm('Usunąć nagranie?')) return; try { await MZ.adminSetStatus(id, 'removed'); onToast('Usunięte'); load(); } catch(e){ onToast(e.message); } }; return (
Treści

Wszystkie nagrania ({items.length})

{['all','collision','near-miss','wildlife','weather','other'].map(s => ( ))}
{list.map(v => ( ))}
TytułAutorLokalizacjaRodzajGłosyWyśw.Akcje
{ e.preventDefault(); setRoute({name:'video', id:v.id}); }}>{v.title} @{v.author_profile?.handle || '—'} {v.city || '—'} {SEV_PL[v.severity] || v.severity} +{fmt((v.up||0) - (v.down||0))} {fmt(v.views)}
); } function AdminReports({ onToast }) { const [items, setItems] = useState([]); const load = async () => setItems(await MZ.adminListReports()); useEffect(() => { load(); }, []); const act = async (id, patch) => { try { await MZ.adminUpdateReport(id, patch); onToast('Zaktualizowane'); load(); } catch(e) { onToast(e.message); } }; return (
Bezpieczeństwo

Zgłoszenia ({items.length})

{items.length === 0 ? : items.map(r => ( )) }
NagranieZgłaszającyPowódOtwarteStatusAkcje
Brak zgłoszeń.
{r.video?.title || '—'} @{r.reporter_profile?.handle || '—'} {r.reason}{r.details ? ` — ${r.details}` : ''} {fmtDate(r.created_at)} {r.status}
); } function AdminUsers({ setRoute, onToast }) { const [items, setItems] = useState([]); const load = async () => setItems(await MZ.adminListUsers()); useEffect(() => { load(); }, []); const setRole = async (id, role) => { try { await MZ.adminUpdateUserRole(id, role); onToast('Rola zmieniona'); load(); } catch(e) { onToast(e.message); } }; return (
Osoby

Użytkownicy ({items.length})

{items.map(u => ( ))}
NickImięRolaDołączyłKarmaAkcje
{ e.preventDefault(); setRoute({name:'account', id:u.id}); }} style={{borderBottom:'1px solid var(--line-2)'}} className="mono">@{u.handle} {u.name || '—'} {fmtDate(u.joined)} {fmt(u.karma)}
); } Object.assign(window, { Account, Admin });