"use client"; import { ReactNode, useState, useEffect } from "react"; interface PhoneKpis { callsToday: number; callsTodayTrend: number; uniqueNumbers: number; topSourceElement: string | null; topSourceElementPercent: number; } interface PhoneNumber { phone_number: string; click_count: number; } interface ElementStat { source_element: string; count: number; percent: number; } interface TimeseriesEntry { date: string; count: number; } interface PhoneData { kpis: PhoneKpis; phoneNumbers: PhoneNumber[]; elements: ElementStat[]; timeseries: TimeseriesEntry[]; } function balkenBreite(wert: number, max: number): string { if (max === 0) return "0%"; return `${Math.max(4, Math.round((wert / max) * 100))}%`; } function PhoneCallsView() { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [range, setRange] = useState("30days"); useEffect(() => { setLoading(true); fetch(`/api/admin/analytics/phone-calls?range=${range}`) .then((r) => r.json()) .then((d) => { setData(d); setLoading(false); }) .catch(() => setLoading(false)); }, [range]); if (loading) { return
Lädt Phone-Click-Daten…
; } if (!data) { return
Fehler beim Laden der Daten
; } const maxTimeseries = Math.max(0, ...data.timeseries.map((t) => t.count)); const maxElements = Math.max(0, ...data.elements.map((e) => e.count)); return (
{/* Header */}

Phone-Click-Tracking

Telefon-Link-Klicks · DSGVO-konform

{[["today", "Heute"], ["7days", "7 Tage"], ["30days", "30 Tage"]].map(([val, label]) => ( ))}
{/* KPI-Cards */}
Klicks heute
{data.kpis.callsToday}
{data.kpis.callsTodayTrend !== 0 && (
0 ? "text-green-400" : "text-red-400"}`}> {data.kpis.callsTodayTrend > 0 ? "+" : ""}{data.kpis.callsTodayTrend}% vs. gestern
)}
Eindeutige Nummern
{data.kpis.uniqueNumbers}
Top Quelle
{data.kpis.topSourceElement ?? "–"}
{data.kpis.topSourceElementPercent > 0 && (
{data.kpis.topSourceElementPercent}% aller Klicks
)}
Klicks gesamt
{data.phoneNumbers.reduce((s, p) => s + p.click_count, 0)}
{/* Zeitreihe */} {data.timeseries.length > 0 && (

Klicks über Zeit

{data.timeseries.map(({ date, count }) => (
{date}
{count}
))}
)} {/* Quellen */} {data.elements.length > 0 && (

Klicks nach Quelle

{data.elements.map(({ source_element, count }) => (
{source_element}
{count}
))}
)} {/* Nummern-Tabelle */} {data.phoneNumbers.length > 0 && (

Gerufene Nummern

{data.phoneNumbers.map((p) => ( ))}
Telefonnummer Klicks
{p.phone_number} {p.click_count}
)} {data.phoneNumbers.length === 0 && (
Noch keine Phone-Klicks im gewählten Zeitraum
)}
); } export function AnalyticsTabs({ overviewContent }: { overviewContent: ReactNode }) { const [activeTab, setActiveTab] = useState<"overview" | "phone">("overview"); return (
{[ { key: "overview", label: "Seitenaufrufe" }, { key: "phone", label: "Phone-Klicks" }, ].map((tab) => ( ))}
{activeTab === "overview" ? overviewContent : }
); }