update viewers page

This commit is contained in:
2026-05-16 08:13:13 +01:00
parent 752b5f9eb8
commit bcade3392f
+52 -13
View File
@@ -2265,7 +2265,6 @@ function ViewersPage({ viewers }) {
const activePages = data.active_pages || [] const activePages = data.active_pages || []
const activity24h = filledLast24Hours(data.activity_24h || []) const activity24h = filledLast24Hours(data.activity_24h || [])
const activity30d = filledLast30Days(data.activity_30d || []) const activity30d = filledLast30Days(data.activity_30d || [])
const dataTypes = data.data_types || []
const totals = data.totals || {} const totals = data.totals || {}
const generatedAt = data.generated_at ? dateFormat.format(new Date(data.generated_at)) : 'Waiting for data' const generatedAt = data.generated_at ? dateFormat.format(new Date(data.generated_at)) : 'Waiting for data'
const periods = { const periods = {
@@ -2326,7 +2325,7 @@ function ViewersPage({ viewers }) {
{Object.entries(periods).map(([key, period]) => ( {Object.entries(periods).map(([key, period]) => (
<button <button
className={`rounded px-3 py-1.5 transition ${ className={`rounded px-3 py-1.5 transition ${
analyticsWindow === key ? 'bg-fury-red text-bg shadow-sm' : 'text-text-soft hover:text-text' analyticsWindow === key ? 'bg-fury-red text-fury-violet shadow-sm' : 'text-text-soft hover:text-text'
}`} }`}
key={key} key={key}
onClick={() => setAnalyticsWindow(key)} onClick={() => setAnalyticsWindow(key)}
@@ -2489,18 +2488,10 @@ function ViewersPage({ viewers }) {
<div className="grid gap-6 xl:grid-cols-[0.9fr_1.1fr]"> <div className="grid gap-6 xl:grid-cols-[0.9fr_1.1fr]">
<div className="rounded-lg border border-border bg-fury-white shadow-sm"> <div className="rounded-lg border border-border bg-fury-white shadow-sm">
<div className="border-b border-surface px-5 py-4"> <div className="border-b border-surface px-5 py-4">
<h2 className="text-lg font-semibold">Collected data types</h2> <h2 className="text-lg font-semibold">Locations</h2>
<p className="mt-1 text-sm text-text-soft"> <p className="mt-1 text-sm text-text-soft">Cities and locations seen over {periodData.title.toLowerCase()}</p>
Optional fields only appear for visitors who explicitly allow them
</p>
</div> </div>
{dataTypes.map((item) => ( <LocationSignalTable countries={periodData.countries} locations={periodData.locations} />
<div className="border-b border-surface px-5 py-3 text-sm" key={item.key}>
<p className="font-semibold">{item.label}</p>
<p className="mt-1 text-text-soft">{item.detail}</p>
</div>
))}
{!dataTypes.length ? <p className="px-5 py-10 text-sm text-text-soft">No collection manifest returned</p> : null}
</div> </div>
<div className="rounded-lg border border-border bg-fury-white shadow-sm"> <div className="rounded-lg border border-border bg-fury-white shadow-sm">
@@ -2522,6 +2513,54 @@ function ViewersPage({ viewers }) {
) )
} }
function LocationSignalTable({ countries, locations }) {
const rows = locations.length
? locations.map((location) => ({
key: `${location.country}-${location.region}-${location.city}-${location.latitude}-${location.longitude}-${location.timezone}`,
place: location.city || location.region || location.timezone || 'Unknown city',
region: location.region || 'Not shared',
country: countryNames[location.country] || location.country || 'Not shared',
visitors: location.visitors,
events: location.events,
}))
: countries.map((country) => ({
key: country.country,
place: countryNames[country.country] || country.country || 'Unknown country',
region: 'Country signal',
country: countryNames[country.country] || country.country || 'Not shared',
visitors: country.visitors,
events: country.events,
}))
return (
<div className="overflow-x-auto">
<table className="w-full min-w-[520px] text-left text-sm">
<thead className="border-b border-surface text-xs uppercase tracking-wide text-text-soft">
<tr>
<th className="px-5 py-3 font-semibold">City/location</th>
<th className="px-5 py-3 font-semibold">Region</th>
<th className="px-5 py-3 font-semibold">Country</th>
<th className="px-5 py-3 text-right font-semibold">Visitors</th>
<th className="px-5 py-3 text-right font-semibold">Events</th>
</tr>
</thead>
<tbody>
{rows.map((row) => (
<tr className="border-b border-surface" key={row.key}>
<td className="px-5 py-3 font-semibold">{row.place}</td>
<td className="px-5 py-3 text-text-soft">{row.region}</td>
<td className="px-5 py-3 text-text-soft">{row.country}</td>
<td className="px-5 py-3 text-right font-semibold text-fury-cyan">{formatNumber(row.visitors)}</td>
<td className="px-5 py-3 text-right text-text-soft">{formatNumber(row.events)}</td>
</tr>
))}
</tbody>
</table>
{!rows.length ? <p className="px-5 py-10 text-sm text-text-soft">No location data recorded yet</p> : null}
</div>
)
}
function LocationSignalMap({ countries, locations }) { function LocationSignalMap({ countries, locations }) {
const mapRef = useRef(null) const mapRef = useRef(null)
const markersRef = useRef(null) const markersRef = useRef(null)