/* 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 (
);
}
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(`
`);
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} NAGRAŃ
{stats.users} AUTORÓW
{fmt(stats.views)} WYŚWIETLEŃ
{['all','collision','near-miss','wildlife','weather','other'].map(f => (
setFilter(f)}>{SEV_PL[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 });