82 lines
4.1 KiB
JavaScript
82 lines
4.1 KiB
JavaScript
import React from 'react'
|
|
|
|
function KpiCard({ icon, label, value, color = 'text-sky-400' }) {
|
|
return (
|
|
<div className="bg-white/4 ring-1 ring-white/10 rounded-2xl p-5 shadow-xl shadow-black/20 backdrop-blur flex items-center gap-4">
|
|
<div className={`w-12 h-12 rounded-xl bg-white/5 flex items-center justify-center shrink-0 ${color}`}>
|
|
<i className={`fa-solid ${icon} text-xl`} />
|
|
</div>
|
|
<div>
|
|
<p className="text-2xl font-bold text-white tabular-nums">{Number(value ?? 0).toLocaleString()}</p>
|
|
<p className="text-xs text-slate-500 mt-0.5 uppercase tracking-wider">{label}</p>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
/**
|
|
* TabStats
|
|
* KPI overview cards. Charts can be added here once chart infrastructure exists.
|
|
*/
|
|
export default function TabStats({ stats, followerCount, followAnalytics }) {
|
|
const kpis = [
|
|
{ icon: 'fa-eye', label: 'Profile Views', value: stats?.profile_views_count, color: 'text-sky-400' },
|
|
{ icon: 'fa-images', label: 'Uploads', value: stats?.uploads_count, color: 'text-violet-400' },
|
|
{ icon: 'fa-download', label: 'Downloads', value: stats?.downloads_received_count, color: 'text-green-400' },
|
|
{ icon: 'fa-eye', label: 'Artwork Views', value: stats?.artwork_views_received_count, color: 'text-blue-400' },
|
|
{ icon: 'fa-heart', label: 'Favourites Received', value: stats?.favourites_received_count, color: 'text-pink-400' },
|
|
{ icon: 'fa-users', label: 'Followers', value: followerCount, color: 'text-amber-400' },
|
|
{ icon: 'fa-trophy', label: 'Awards Received', value: stats?.awards_received_count, color: 'text-yellow-400' },
|
|
{ icon: 'fa-comment', label: 'Comments Received', value: stats?.comments_received_count, color: 'text-orange-400' },
|
|
]
|
|
const trendCards = [
|
|
{ icon: 'fa-arrow-trend-up', label: 'Followers Today', value: followAnalytics?.daily?.gained ?? 0, color: 'text-emerald-400' },
|
|
{ icon: 'fa-user-minus', label: 'Unfollows Today', value: followAnalytics?.daily?.lost ?? 0, color: 'text-rose-400' },
|
|
{ icon: 'fa-chart-line', label: 'Weekly Net', value: followAnalytics?.weekly?.net ?? 0, color: 'text-sky-400' },
|
|
{ icon: 'fa-percent', label: 'Weekly Growth %', value: followAnalytics?.weekly?.growth_rate ?? 0, color: 'text-amber-400' },
|
|
]
|
|
|
|
const hasStats = stats !== null && stats !== undefined
|
|
|
|
return (
|
|
<div
|
|
id="tabpanel-stats"
|
|
role="tabpanel"
|
|
aria-labelledby="tab-stats"
|
|
className="pt-6"
|
|
>
|
|
{!hasStats ? (
|
|
<div className="bg-white/4 ring-1 ring-white/10 rounded-2xl p-10 text-center shadow-xl shadow-black/20">
|
|
<i className="fa-solid fa-chart-bar text-3xl text-slate-600 mb-3 block" />
|
|
<p className="text-slate-400 font-medium">No stats available yet</p>
|
|
<p className="text-slate-600 text-sm mt-1">Stats will appear once there is activity on this profile.</p>
|
|
</div>
|
|
) : (
|
|
<>
|
|
<h2 className="text-xs font-semibold uppercase tracking-widest text-slate-500 mb-4 flex items-center gap-2">
|
|
<i className="fa-solid fa-chart-bar text-green-400 fa-fw" />
|
|
Lifetime Statistics
|
|
</h2>
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-3">
|
|
{kpis.map((kpi) => (
|
|
<KpiCard key={kpi.label} {...kpi} />
|
|
))}
|
|
</div>
|
|
<h3 className="mt-8 mb-4 text-xs font-semibold uppercase tracking-widest text-slate-500 flex items-center gap-2">
|
|
<i className="fa-solid fa-user-group text-emerald-400 fa-fw" />
|
|
Follow Growth
|
|
</h3>
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3">
|
|
{trendCards.map((card) => (
|
|
<KpiCard key={card.label} {...card} />
|
|
))}
|
|
</div>
|
|
<p className="text-xs text-slate-600 mt-6 text-center">
|
|
More detailed analytics (charts, trends) coming soon.
|
|
</p>
|
|
</>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|