Files
flyer-crawler.projectium.com/src/pages/admin/AdminStatsPage.tsx

104 lines
3.6 KiB
TypeScript

// src/pages/admin/AdminStatsPage.tsx
import React, { useEffect, useState } from 'react';
import { Link } from 'react-router-dom';
import { getApplicationStats, AppStats } from '../../services/apiClient';
import { logger } from '../../services/logger.client';
import { LoadingSpinner } from '../../components/LoadingSpinner';
import { ChartBarIcon } from '../../components/icons/ChartBarIcon';
import { UsersIcon } from '../../components/icons/UsersIcon';
import { DocumentDuplicateIcon } from '../../components/icons/DocumentDuplicateIcon';
import { BuildingStorefrontIcon } from '../../components/icons/BuildingStorefrontIcon';
import { BellAlertIcon } from '../../components/icons/BellAlertIcon';
import { BookOpenIcon } from '../../components/icons/BookOpenIcon';
import { StatCard } from '../../components/StatCard';
export const AdminStatsPage: React.FC = () => {
const [stats, setStats] = useState<AppStats | null>(null);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
const fetchStats = async () => {
setIsLoading(true);
setError(null);
try {
const response = await getApplicationStats();
const data = await response.json();
setStats(data);
} catch (err) {
const errorMessage = err instanceof Error ? err.message : 'An unknown error occurred.';
logger.error({ err }, 'Failed to fetch application stats');
setError(errorMessage);
} finally {
setIsLoading(false);
}
};
fetchStats();
}, []);
return (
<div className="max-w-5xl mx-auto py-8 px-4">
<div className="mb-8">
<Link to="/admin" className="text-brand-primary hover:underline">
&larr; Back to Admin Dashboard
</Link>
<h1 className="text-3xl font-bold text-gray-800 dark:text-white mt-2">
Application Statistics
</h1>
<p className="text-gray-500 dark:text-gray-400">
A high-level overview of key application metrics.
</p>
</div>
{isLoading && (
<div
role="status"
aria-label="Loading stats"
className="flex justify-center items-center h-64"
>
<LoadingSpinner />
</div>
)}
{error && (
<div className="text-red-500 bg-red-100 dark:bg-red-900/20 p-4 rounded-lg">{error}</div>
)}
{stats && !isLoading && !error && (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<StatCard
title="Total Users"
value={stats.userCount.toLocaleString()}
icon={<UsersIcon className="w-6 h-6" />}
/>
<StatCard
title="Flyers Processed"
value={stats.flyerCount.toLocaleString()}
icon={<DocumentDuplicateIcon className="w-6 h-6" />}
/>
<StatCard
title="Total Flyer Items"
value={stats.flyerItemCount.toLocaleString()}
icon={<ChartBarIcon className="w-6 h-6" />}
/>
<StatCard
title="Stores Tracked"
value={stats.storeCount.toLocaleString()}
icon={<BuildingStorefrontIcon className="w-6 h-6" />}
/>
<StatCard
title="Pending Corrections"
value={stats.pendingCorrectionCount.toLocaleString()}
icon={<BellAlertIcon className="w-6 h-6" />}
/>
<StatCard
title="Total Recipes"
value={stats.recipeCount.toLocaleString()}
icon={<BookOpenIcon className="w-6 h-6" />}
/>
</div>
)}
</div>
);
};