| 1 | import React from 'react'
|
|---|
| 2 | import {
|
|---|
| 3 | LineChart,
|
|---|
| 4 | Line,
|
|---|
| 5 | BarChart,
|
|---|
| 6 | Bar,
|
|---|
| 7 | XAxis,
|
|---|
| 8 | YAxis,
|
|---|
| 9 | CartesianGrid,
|
|---|
| 10 | Tooltip,
|
|---|
| 11 | ResponsiveContainer,
|
|---|
| 12 | } from 'recharts'
|
|---|
| 13 | import { Eye, Heart, MessageCircle, TrendingUp, Clock, BarChart2 } from 'lucide-react'
|
|---|
| 14 | import { mockAnalytics } from '../../data/mockData'
|
|---|
| 15 |
|
|---|
| 16 | const StatCard: React.FC<{ icon: React.ReactNode; label: string; value: string | number; color: string }> = ({
|
|---|
| 17 | icon, label, value, color,
|
|---|
| 18 | }) => (
|
|---|
| 19 | <div className={`p-4 bg-slate-800 rounded-xl border border-slate-700`}>
|
|---|
| 20 | <div className={`w-10 h-10 rounded-xl ${color} flex items-center justify-center mb-3`}>
|
|---|
| 21 | {icon}
|
|---|
| 22 | </div>
|
|---|
| 23 | <p className="text-2xl font-bold text-white">{value.toLocaleString()}</p>
|
|---|
| 24 | <p className="text-slate-400 text-sm mt-0.5">{label}</p>
|
|---|
| 25 | </div>
|
|---|
| 26 | )
|
|---|
| 27 |
|
|---|
| 28 | const CustomTooltip = ({ active, payload, label }: any) => {
|
|---|
| 29 | if (active && payload && payload.length) {
|
|---|
| 30 | return (
|
|---|
| 31 | <div className="bg-slate-800 border border-slate-700 rounded-xl px-3 py-2 text-sm">
|
|---|
| 32 | <p className="text-slate-400 mb-1">{label}</p>
|
|---|
| 33 | {payload.map((p: any) => (
|
|---|
| 34 | <p key={p.dataKey} className="text-white font-medium">
|
|---|
| 35 | {p.name}: {p.value.toLocaleString()}
|
|---|
| 36 | </p>
|
|---|
| 37 | ))}
|
|---|
| 38 | </div>
|
|---|
| 39 | )
|
|---|
| 40 | }
|
|---|
| 41 | return null
|
|---|
| 42 | }
|
|---|
| 43 |
|
|---|
| 44 | export const StoryAnalytics: React.FC = () => {
|
|---|
| 45 | const analytics = mockAnalytics
|
|---|
| 46 | const viewsData = analytics.views_over_time.filter((_, i) => i % 5 === 0)
|
|---|
| 47 | const likesData = analytics.likes_over_time.filter((_, i) => i % 5 === 0)
|
|---|
| 48 |
|
|---|
| 49 | return (
|
|---|
| 50 | <div className="space-y-6">
|
|---|
| 51 | {/* Stat cards */}
|
|---|
| 52 | <div className="grid grid-cols-2 lg:grid-cols-5 gap-4">
|
|---|
| 53 | <StatCard icon={<Eye size={18} className="text-blue-300" />} label="Total Views" value={analytics.total_views} color="bg-blue-500/20" />
|
|---|
| 54 | <StatCard icon={<Heart size={18} className="text-rose-300" />} label="Total Likes" value={analytics.total_likes} color="bg-rose-500/20" />
|
|---|
| 55 | <StatCard icon={<MessageCircle size={18} className="text-violet-300" />} label="Comments" value={analytics.total_comments} color="bg-violet-500/20" />
|
|---|
| 56 | <StatCard icon={<Clock size={18} className="text-amber-300" />} label="Avg Read (min)" value={analytics.avg_read_time} color="bg-amber-500/20" />
|
|---|
| 57 | <StatCard icon={<BarChart2 size={18} className="text-emerald-300" />} label="Completion %" value={`${analytics.completion_rate}%`} color="bg-emerald-500/20" />
|
|---|
| 58 | </div>
|
|---|
| 59 |
|
|---|
| 60 | {/* Views chart */}
|
|---|
| 61 | <div className="bg-slate-800 border border-slate-700 rounded-2xl p-6">
|
|---|
| 62 | <div className="flex items-center gap-2 mb-4">
|
|---|
| 63 | <TrendingUp size={16} className="text-blue-400" />
|
|---|
| 64 | <h3 className="text-white font-semibold">Views Over Time</h3>
|
|---|
| 65 | </div>
|
|---|
| 66 | <ResponsiveContainer width="100%" height={200}>
|
|---|
| 67 | <LineChart data={viewsData}>
|
|---|
| 68 | <CartesianGrid strokeDasharray="3 3" stroke="#334155" />
|
|---|
| 69 | <XAxis dataKey="date" tick={{ fill: '#64748b', fontSize: 11 }} tickLine={false} axisLine={false} />
|
|---|
| 70 | <YAxis tick={{ fill: '#64748b', fontSize: 11 }} tickLine={false} axisLine={false} />
|
|---|
| 71 | <Tooltip content={<CustomTooltip />} />
|
|---|
| 72 | <Line type="monotone" dataKey="views" stroke="#6366f1" strokeWidth={2} dot={false} name="Views" />
|
|---|
| 73 | </LineChart>
|
|---|
| 74 | </ResponsiveContainer>
|
|---|
| 75 | </div>
|
|---|
| 76 |
|
|---|
| 77 | {/* Likes chart */}
|
|---|
| 78 | <div className="bg-slate-800 border border-slate-700 rounded-2xl p-6">
|
|---|
| 79 | <div className="flex items-center gap-2 mb-4">
|
|---|
| 80 | <Heart size={16} className="text-rose-400" />
|
|---|
| 81 | <h3 className="text-white font-semibold">Likes Over Time</h3>
|
|---|
| 82 | </div>
|
|---|
| 83 | <ResponsiveContainer width="100%" height={200}>
|
|---|
| 84 | <BarChart data={likesData}>
|
|---|
| 85 | <CartesianGrid strokeDasharray="3 3" stroke="#334155" />
|
|---|
| 86 | <XAxis dataKey="date" tick={{ fill: '#64748b', fontSize: 11 }} tickLine={false} axisLine={false} />
|
|---|
| 87 | <YAxis tick={{ fill: '#64748b', fontSize: 11 }} tickLine={false} axisLine={false} />
|
|---|
| 88 | <Tooltip content={<CustomTooltip />} />
|
|---|
| 89 | <Bar dataKey="likes" fill="#f43f5e" radius={[4, 4, 0, 0]} name="Likes" />
|
|---|
| 90 | </BarChart>
|
|---|
| 91 | </ResponsiveContainer>
|
|---|
| 92 | </div>
|
|---|
| 93 | </div>
|
|---|
| 94 | )
|
|---|
| 95 | }
|
|---|