'use client' import { useState, useEffect, useRef } from 'react' // ── Helpers ────────────────────────────────────────────────── function rand(min: number, max: number) { return Math.floor(Math.random() * (max - min + 1)) + min } function fmtDuration(seconds: number) { const m = Math.floor(seconds / 60) const s = seconds % 60 return `${m}m ${s}s` } // Generate realistic hourly visitor counts (low at night, peak afternoon) function generateHourlyPattern(): { hour: string; visitors: number; pageviews: number }[] { const base = [ 12, 8, 5, 4, 3, 4, 8, 18, 35, 52, 64, 72, 78, 85, 88, 82, 74, 60, 48, 38, 30, 25, 20, 16, ] return base.map((v, i) => ({ hour: `${String(i).padStart(2, '0')}:00`, visitors: v + rand(-4, 4), pageviews: Math.round(v * 2.8) + rand(-6, 6), })) } // ── Static panel data ──────────────────────────────────────── const topPages = [ { label: '/blog/privacy', pct: 85 }, { label: '/pricing', pct: 65 }, { label: '/docs', pct: 45 }, { label: '/about', pct: 30 }, { label: '/integrations', pct: 20 }, ] const topReferrers = [ { label: 'Google', pct: 40 }, { label: 'Direct', pct: 25 }, { label: 'Twitter', pct: 15 }, { label: 'GitHub', pct: 12 }, { label: 'Reddit', pct: 8 }, ] const locations = [ { flag: '\u{1F1E8}\u{1F1ED}', name: 'Switzerland', pct: 30 }, { flag: '\u{1F1E9}\u{1F1EA}', name: 'Germany', pct: 22 }, { flag: '\u{1F1FA}\u{1F1F8}', name: 'USA', pct: 18 }, { flag: '\u{1F1EB}\u{1F1F7}', name: 'France', pct: 15 }, { flag: '\u{1F1EC}\u{1F1E7}', name: 'UK', pct: 15 }, ] const technology = [ { label: 'Chrome', pct: 62 }, { label: 'Firefox', pct: 18 }, { label: 'Safari', pct: 15 }, { label: 'Edge', pct: 5 }, ] const campaigns = [ { label: 'newsletter', pct: 45 }, { label: 'twitter', pct: 30 }, { label: 'producthunt', pct: 25 }, ] // Generate heatmap data: 7 rows (Mon-Sun) x 24 cols (hours) function generateHeatmap(): number[][] { return Array.from({ length: 7 }, (_, day) => Array.from({ length: 24 }, (_, hour) => { const isWeekend = day >= 5 const isNight = hour >= 1 && hour <= 5 const isPeak = hour >= 9 && hour <= 17 const isMorning = hour >= 7 && hour <= 9 const isEvening = hour >= 17 && hour <= 21 if (isNight) return rand(0, 1) if (isWeekend) { if (isPeak) return rand(2, 4) return rand(1, 3) } if (isPeak) return rand(5, 8) if (isMorning || isEvening) return rand(3, 5) return rand(1, 3) }) ) } function heatmapOpacity(value: number): string { if (value <= 1) return 'bg-brand-orange/[0.05]' if (value <= 3) return 'bg-brand-orange/[0.2]' if (value <= 5) return 'bg-brand-orange/[0.5]' return 'bg-brand-orange/[0.8]' } // ── SVG chart helpers ──────────────────────────────────────── function buildSmoothPath( points: { x: number; y: number }[], close: boolean ): string { if (points.length < 2) return '' const d: string[] = [`M ${points[0].x},${points[0].y}`] for (let i = 0; i < points.length - 1; i++) { const p0 = points[Math.max(i - 1, 0)] const p1 = points[i] const p2 = points[i + 1] const p3 = points[Math.min(i + 2, points.length - 1)] const cp1x = p1.x + (p2.x - p0.x) / 6 const cp1y = p1.y + (p2.y - p0.y) / 6 const cp2x = p2.x - (p3.x - p1.x) / 6 const cp2y = p2.y - (p3.y - p1.y) / 6 d.push(`C ${cp1x},${cp1y} ${cp2x},${cp2y} ${p2.x},${p2.y}`) } if (close) { const last = points[points.length - 1] const first = points[0] d.push(`L ${last.x},200 L ${first.x},200 Z`) } return d.join(' ') } // ── Component ──────────────────────────────────────────────── export default function LiveDemo() { const [visitors, setVisitors] = useState(2847) const [pageviews, setPageviews] = useState(8432) const [bounceRate, setBounceRate] = useState(42) const [avgDuration, setAvgDuration] = useState(154) const [realtimeVisitors, setRealtimeVisitors] = useState(12) const [chartData, setChartData] = useState(generateHourlyPattern) const heatmap = useRef(generateHeatmap()) useEffect(() => { const id = setInterval(() => { setVisitors((v) => v + rand(1, 3)) setPageviews((v) => v + rand(2, 5)) setBounceRate(() => 38 + rand(0, 7)) setAvgDuration(() => 130 + rand(0, 90)) setRealtimeVisitors(() => 8 + rand(0, 7)) setChartData((prev) => { const next = [...prev] const lastHourNum = parseInt(next[next.length - 1].hour.split(':')[0], 10) const newHour = (lastHourNum + 1) % 24 next.push({ hour: `${String(newHour).padStart(2, '0')}:00`, visitors: rand(20, 90), pageviews: rand(50, 250), }) if (next.length > 24) next.shift() return next }) }, 2500) return () => clearInterval(id) }, []) // ── Chart SVG ────────────────────────────────────────────── const chartW = 800 const chartH = 200 const maxVisitors = Math.max(...chartData.map((d) => d.visitors), 1) const chartPoints = chartData.map((d, i) => ({ x: (i / (chartData.length - 1)) * chartW, y: chartH - (d.visitors / maxVisitors) * (chartH - 20) - 10, })) const linePath = buildSmoothPath(chartPoints, false) const areaPath = buildSmoothPath(chartPoints, true) // ── Stats config ─────────────────────────────────────────── const stats = [ { label: 'Visitors', value: visitors.toLocaleString(), change: '+12%', positive: true, }, { label: 'Pageviews', value: pageviews.toLocaleString(), change: '+8%', positive: true, }, { label: 'Bounce Rate', value: `${bounceRate}%`, change: '-3%', positive: false, }, { label: 'Avg. Duration', value: fmtDuration(avgDuration), change: '+15%', positive: true, }, ] const xLabels = chartData .map((d, i) => ({ label: d.hour, i })) .filter((d) => parseInt(d.label.split(':')[0], 10) % 4 === 0) const dayLabels = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] // ── Render ───────────────────────────────────────────────── return (
{/* Browser chrome */}
pulse.ciphera.net/sites/demo
{/* Dashboard body */}
{/* Header bar */}
Ciphera ciphera.net {realtimeVisitors} current visitors
Today
{/* Stats bar */}
{stats.map((s) => (
{s.label}
{s.value}
{s.positive ? '\u2191' : '\u2193'} {s.change.replace(/[+-]/, '')}
))}
{/* Chart */}
{/* X-axis labels */} {xLabels.map(({ label, i }) => ( {label} ))}
{/* Two-column panels */}
{/* Top Pages */} {/* Top Referrers */} {/* Locations */}

Locations

{locations.map((loc) => (
{loc.flag} {loc.name} {loc.pct}%
))}
{/* Technology */} {/* Campaigns */} {/* Peak Hours */}

Peak Hours

{heatmap.current.map((row, dayIdx) => (
{dayLabels[dayIdx]}
{row.map((val, hourIdx) => (
))}
))}
{/* Bottom gradient fade */}
) } // ── Panel Card sub-component ───────────────────────────────── function PanelCard({ title, items, }: { title: string items: { label: string; pct: number }[] }) { return (

{title}

{items.map((item) => (
{item.label} {item.pct}%
))}
) }