humanizerx / src /components /StatsGrid.tsx
mmrwinston001's picture
Upload 32 files (#3)
6ce679b verified
// src/components/StatsGrid.tsx
import React, { useContext } from 'react';
import { TrendingUp, FileText, Zap, Target } from 'lucide-react';
import { ThemeContext } from '../contexts/ThemeContext';
import { useUserStats } from '../hooks/useUserStats';
const StatsGrid: React.FC = () => {
const { theme } = useContext(ThemeContext);
const { stats } = useUserStats(); // Live stats from Firestore
const isDark = theme === 'dark';
// --- Safely parse all stats ---
const textsHumanized = Number(stats?.textsHumanized ?? 0);
const wordsProcessed = Number(stats?.wordsProcessed ?? 0);
const totalSessions = Number(stats?.totalSessions ?? 0);
const gptAverage = Number(stats?.gptAverage ?? 0);
// --- Format derived stats ---
const gptAverageDisplay = `${gptAverage.toFixed(1)}%`;
const statItems = [
{
label: 'Texts Humanized',
value: textsHumanized.toLocaleString(),
icon: FileText,
color: 'blue',
change: '+12%',
},
{
label: 'Words Processed',
value: wordsProcessed.toLocaleString(),
icon: Zap,
color: 'green',
change: '+8%',
},
{
label: 'GPT Average',
value: gptAverageDisplay,
icon: Target,
color: 'purple',
change: '+3%',
},
{
label: 'Total Sessions',
value: totalSessions.toLocaleString(),
icon: TrendingUp,
color: 'orange',
change: '+15%',
},
];
const getColorClasses = (color: string) => {
const colors = {
blue: `bg-${isDark ? 'blue-800' : 'blue-50'} text-${
isDark ? 'blue-300' : 'blue-600'
} border-${isDark ? 'blue-700' : 'blue-200'}`,
green: `bg-${isDark ? 'green-800' : 'green-50'} text-${
isDark ? 'green-300' : 'green-600'
} border-${isDark ? 'green-700' : 'green-200'}`,
purple: `bg-${isDark ? 'purple-800' : 'purple-50'} text-${
isDark ? 'purple-300' : 'purple-600'
} border-${isDark ? 'purple-700' : 'purple-200'}`,
orange: `bg-${isDark ? 'orange-800' : 'orange-50'} text-${
isDark ? 'orange-300' : 'orange-600'
} border-${isDark ? 'orange-700' : 'orange-200'}`,
};
return colors[color as keyof typeof colors] || colors.blue;
};
const cardBgClass = isDark
? 'bg-gray-900 border-gray-700 text-white'
: 'bg-white border-gray-200 text-gray-900';
return (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
{statItems.map((item, index) => {
const Icon = item.icon;
return (
<div
key={index}
className={`rounded-xl border p-6 hover:shadow-md transition-shadow ${cardBgClass}`}
>
<div className="flex items-center justify-between mb-4">
<div className={`p-3 rounded-lg ${getColorClasses(item.color)}`}>
<Icon className="w-6 h-6" />
</div>
<span
className={`text-sm font-medium px-2 py-1 rounded ${
isDark
? 'bg-gray-800 text-green-400'
: 'bg-green-50 text-green-600'
}`}
>
{item.change}
</span>
</div>
<div>
<p
className={`text-2xl font-bold mb-1 ${
isDark ? 'text-white' : 'text-gray-900'
}`}
>
{item.value || '0'}
</p>
<p
className={`text-sm ${
isDark ? 'text-gray-300' : 'text-gray-600'
}`}
>
{item.label}
</p>
</div>
</div>
);
})}
</div>
);
};
export default StatsGrid;