/* global React, L, MZ */ const { useState, useEffect, useRef } = React; function Header({ route, setRoute, user, profile, onLogin, onSubmit, onLogout }) { const [q, setQ] = useState(''); const onSearch = (e) => { e.preventDefault(); if (q.trim()) setRoute({ name: 'search', q: q.trim() }); }; return (
{ e.preventDefault(); setRoute({name:'home'}); }} className="logo"> MiejsceZdarzenia.pl
setQ(e.target.value)} />
{user ? ( <> { e.preventDefault(); setRoute({name:'account', id:user.id}); }} className="avatar" title={profile?.handle || ''}>{initials(profile?.name || profile?.handle || 'U')} ) : ( )}
); } function Footer({ setRoute }) { return ( ); } function VideoCard({ video, onOpen }) { const u = video.author_profile || {}; const score = (video.up || 0) - (video.down || 0); return (
onOpen(video.id)}>
{SEV_PL[video.severity] || video.severity} {video.duration && {video.duration}}
{video.title}
{video.city || '—'} {timeAgo(video.created_at)}
@{u.handle || 'anon'} {fmt(score)}
); } function RankedRow({ video, rank, onOpen }) { const score = (video.up || 0) - (video.down || 0); return (
onOpen(video.id)}>
{String(rank).padStart(2, '0')}
{video.duration && {video.duration}}
{video.title}
{video.city || '—'} · {fmt(video.views)} wyświetleń
+{fmt(score)}
GŁOSY NETTO
); } function HomeMap({ theme, onOpen, filter, videos }) { const mapRef = useRef(null); const instRef = useRef(null); const tileRef = useRef(null); const markersRef = useRef([]); useEffect(() => { if (instRef.current) return; const map = L.map(mapRef.current, { zoomControl: true, worldCopyJump: true }).setView([52, 19], 6); instRef.current = map; return () => { map.remove(); instRef.current = null; }; }, []); useEffect(() => { const map = instRef.current; if (!map) return; if (tileRef.current) map.removeLayer(tileRef.current); const t = TILES[theme === 'dark' ? 'dark' : 'light']; tileRef.current = L.tileLayer(t.url, { attribution: t.attr, subdomains: 'abcd', maxZoom: 19 }).addTo(map); }, [theme]); useEffect(() => { const map = instRef.current; if (!map) return; markersRef.current.forEach(m => map.removeLayer(m)); markersRef.current = []; const filtered = filter === 'all' ? videos : videos.filter(v => v.severity === filter); filtered.forEach(v => { const icon = L.divIcon({ className: '', html: `
`, iconSize: [14,14], iconAnchor: [7,7] }); const m = L.marker([v.lat, v.lng], { icon }).addTo(map); m.bindPopup(` OBEJRZYJ NAGRANIE → `); markersRef.current.push(m); }); }, [filter, videos]); useEffect(() => { const handler = (e) => { const a = e.target.closest('.popup-link'); if (a) { e.preventDefault(); onOpen(a.dataset.vid); } }; document.addEventListener('click', handler); return () => document.removeEventListener('click', handler); }, [onOpen]); return
; } function Home({ setRoute, theme }) { const [filter, setFilter] = useState('all'); const [videos, setVideos] = useState([]); const [top, setTop] = useState([]); const [loading, setLoading] = useState(true); const [stats, setStats] = useState({ videos: 0, users: 0, views: 0 }); useEffect(() => { (async () => { try { const [all, t, s] = await Promise.all([ MZ.listVideos({ limit: 200 }), MZ.topVideos(8), MZ.stats(), ]); setVideos(all); setTop(t); const totalViews = all.reduce((a,v) => a + (v.views||0), 0); setStats({ videos: s.videos, users: s.users, views: totalViews }); } catch (e) { console.error(e); } setLoading(false); })(); }, []); const latest = videos.slice(0, 8); const open = (id) => setRoute({ name: 'video', id }); return (

{stats.videos === 0 ? 'Jeszcze nie dodano żadnego nagrania.' : `${stats.videos} ${stats.videos === 1 ? 'nagranie' : 'nagrań'} zebranych i przypiętych do miejsc zdarzeń.`}

Społecznościowe archiwum nagrań z wideorejestratorów z Polski — wypadki, niebezpieczne sytuacje, pogoda i zwierzęta na drodze. Przeglądaj według lokalizacji.

{stats.videos === 0 && (

{ e.preventDefault(); setRoute({ name:'home', openSubmit: true }); window.dispatchEvent(new CustomEvent('mz-open-submit')); }} style={{borderBottom:'1px solid var(--accent)', color:'var(--accent)'}}>Bądź pierwszy — dodaj nagranie →

)}
{stats.videos}NAGRAŃ
{stats.users}AUTORÓW
{fmt(stats.views)}WYŚWIETLEŃ
{['all','collision','near-miss','wildlife','weather','other'].map(f => ( ))}
RODZAJ ZDARZENIA
kolizja
prawie-kolizja
zwierzęta
pogoda
{top.length > 0 && (
— Najczęściej głosowane · od zawsze

Najwyżej oceniane nagrania

{top.map((v, i) => )}
)} {latest.length > 0 && (
— Dopiero co dodane

Najnowsze zgłoszenia

{latest.map(v => )}
)} {!loading && videos.length === 0 && (

Witamy w MiejsceZdarzenia.pl

Serwis dopiero co wystartował. Zaloguj się i dodaj pierwsze nagranie z wideorejestratora — może to być link do filmu z YouTube.

)}
); } function SearchPage({ query, setRoute }) { const [results, setResults] = useState([]); const [loading, setLoading] = useState(true); useEffect(() => { (async () => { setLoading(true); try { setResults(await MZ.searchVideos(query)); } catch(e) { console.error(e); } setLoading(false); })(); }, [query]); return (
— Wyniki wyszukiwania

"{query}"

{loading ? 'WYSZUKIWANIE…' : `ZNALEZIONO ${results.length}`}
{!loading && results.length === 0 && (

Brak wyników dla zapytania „{query}". Spróbuj innego słowa lub nazwy miasta.

)}
{results.map(v => setRoute({name:'video', id})} />)}
); } Object.assign(window, { Header, Footer, Home, VideoCard, RankedRow, SearchPage });