Skip to content

Commit 61d6b0f

Browse files
Refactor: Ensure Supabase integration
1 parent 884118d commit 61d6b0f

11 files changed

+1078
-303
lines changed

src/components/AdminDashboard.tsx

Lines changed: 21 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
import { useEffect, useState } from 'react';
22
import { useAdminAuth } from '@/hooks/useAdminAuth';
33
import { useServiceHealth } from '@/hooks/useServiceHealth';
4-
import { useFirestoreMonitoring } from '@/hooks/useFirestoreMonitoring';
4+
import { useSupabaseMonitoring } from '@/hooks/useSupabaseMonitoring';
55
import { useProductionDBMonitoring } from '@/hooks/useProductionDBMonitoring';
6-
import { collection, getDocs, getCountFromServer } from 'firebase/firestore';
7-
import { db } from '@/lib/firebase';
6+
// Suppression des imports Firebase - utilisation de Supabase maintenant
7+
// import { collection, getDocs, getCountFromServer } from 'firebase/firestore';
8+
// import { db } from '@/lib/firebase';
89
import Logger from '@/utils/logger';
910
import { AdminHeader } from './admin/AdminHeader';
1011
import { SystemStatusCard } from './admin/SystemStatusCard';
1112
import { SystemMetricsGrid } from './admin/SystemMetricsGrid';
1213
import { ServiceHealthList } from './admin/ServiceHealthList';
1314
import { AdminActions } from './admin/AdminActions';
14-
import { FirestoreMetricsCard } from './admin/FirestoreMetricsCard';
15+
import { SupabaseMetricsCard } from './admin/SupabaseMetricsCard';
1516
import { ProductionDBCard } from './admin/ProductionDBCard';
1617

1718
interface SystemStats {
@@ -32,7 +33,7 @@ interface SystemHealth {
3233
export const AdminDashboard = () => {
3334
const { currentEmail, adminEmail } = useAdminAuth();
3435
const { healthChecks, isChecking, lastUpdate, runHealthChecks } = useServiceHealth();
35-
const { metrics: firestoreMetrics, isLoading: isFirestoreLoading, refreshMetrics } = useFirestoreMonitoring();
36+
const { metrics: supabaseMetrics, isLoading: isSupabaseLoading, refreshMetrics } = useSupabaseMonitoring();
3637
const { metrics: productionMetrics, isLoading: isProductionLoading, refreshMetrics: refreshProductionMetrics } = useProductionDBMonitoring();
3738
const [systemStats, setSystemStats] = useState<SystemStats>({
3839
totalCollections: 0,
@@ -56,45 +57,21 @@ export const AdminDashboard = () => {
5657

5758
const loadSystemStats = async () => {
5859
try {
59-
Logger.admin('Loading real system statistics');
60-
61-
// Compter les documents dans les collections principales
62-
const collections = ['campaigns', 'affiliates', 'clicks', 'conversions'];
63-
let totalDocs = 0;
64-
65-
for (const collectionName of collections) {
66-
try {
67-
const countQuery = await getCountFromServer(collection(db, collectionName));
68-
totalDocs += countQuery.data().count;
69-
} catch (error) {
70-
Logger.warning(`Could not count ${collectionName}, falling back to getDocs`);
71-
const snapshot = await getDocs(collection(db, collectionName));
72-
totalDocs += snapshot.size;
73-
}
74-
}
75-
76-
// Calculer les vraies métriques basées sur les health checks
77-
const avgResponseTime = healthChecks.length > 0
78-
? Math.round(healthChecks.reduce((sum, check) => sum + check.responseTime, 0) / healthChecks.length)
79-
: 0;
80-
81-
const healthyServices = healthChecks.filter(check => check.status === 'operational').length;
82-
83-
setSystemStats({
84-
totalCollections: collections.length,
85-
totalDocuments: totalDocs,
86-
averageResponseTime: avgResponseTime,
87-
healthyServices,
60+
Logger.admin('Loading system statistics from Supabase');
61+
62+
// Utiliser les métriques Supabase au lieu de Firebase
63+
const stats = {
64+
totalCollections: 4, // campaigns, affiliates, clicks, conversions
65+
totalDocuments: supabaseMetrics.totalCampaigns + supabaseMetrics.totalAffiliates + supabaseMetrics.totalClicks + supabaseMetrics.totalConversions,
66+
averageResponseTime: supabaseMetrics.avgResponseTime,
67+
healthyServices: healthChecks.filter(check => check.status === 'operational').length,
8868
totalServices: healthChecks.length,
8969
lastUpdateTime: new Date(),
90-
});
70+
};
71+
72+
setSystemStats(stats);
9173

92-
Logger.admin('Real system stats loaded', {
93-
totalDocuments: totalDocs,
94-
avgResponseTime,
95-
healthyServices,
96-
totalServices: healthChecks.length
97-
});
74+
Logger.admin('System stats loaded from Supabase', stats);
9875
} catch (error) {
9976
Logger.error('ADMIN - Error loading system stats', error);
10077
} finally {
@@ -176,9 +153,9 @@ export const AdminDashboard = () => {
176153
onRefresh={refreshProductionMetrics}
177154
/>
178155

179-
<FirestoreMetricsCard
180-
metrics={firestoreMetrics}
181-
isLoading={isFirestoreLoading}
156+
<SupabaseMetricsCard
157+
metrics={supabaseMetrics}
158+
isLoading={isSupabaseLoading}
182159
onRefresh={refreshMetrics}
183160
/>
184161

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
2+
import { Button } from '@/components/ui/button';
3+
import { Database, RefreshCw, TrendingUp, Users, MousePointer, DollarSign } from 'lucide-react';
4+
import { SupabaseMetrics } from '@/hooks/useSupabaseMonitoring';
5+
6+
interface SupabaseMetricsCardProps {
7+
metrics: SupabaseMetrics;
8+
isLoading: boolean;
9+
onRefresh: () => void;
10+
}
11+
12+
export const SupabaseMetricsCard = ({ metrics, isLoading, onRefresh }: SupabaseMetricsCardProps) => {
13+
const formatCurrency = (amount: number) => {
14+
return new Intl.NumberFormat('fr-FR', {
15+
style: 'currency',
16+
currency: 'EUR'
17+
}).format(amount);
18+
};
19+
20+
const formatNumber = (num: number) => {
21+
return new Intl.NumberFormat('fr-FR').format(num);
22+
};
23+
24+
return (
25+
<Card className="w-full">
26+
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
27+
<div className="flex items-center gap-2">
28+
<Database className="h-5 w-5 text-green-600" />
29+
<CardTitle className="text-lg font-semibold">
30+
Monitoring Supabase
31+
</CardTitle>
32+
</div>
33+
<Button
34+
variant="outline"
35+
size="sm"
36+
onClick={onRefresh}
37+
disabled={isLoading}
38+
className="h-8 w-8 p-0"
39+
>
40+
<RefreshCw className={`h-4 w-4 ${isLoading ? 'animate-spin' : ''}`} />
41+
</Button>
42+
</CardHeader>
43+
<CardDescription className="px-6 pb-4">
44+
Métriques en temps réel de votre base de données Supabase
45+
</CardDescription>
46+
47+
<CardContent>
48+
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
49+
{/* Campagnes */}
50+
<div className="flex flex-col items-center p-4 bg-blue-50 rounded-lg">
51+
<TrendingUp className="h-8 w-8 text-blue-600 mb-2" />
52+
<div className="text-2xl font-bold text-blue-900">
53+
{formatNumber(metrics.totalCampaigns)}
54+
</div>
55+
<div className="text-sm text-blue-700">Campagnes</div>
56+
</div>
57+
58+
{/* Affiliés */}
59+
<div className="flex flex-col items-center p-4 bg-purple-50 rounded-lg">
60+
<Users className="h-8 w-8 text-purple-600 mb-2" />
61+
<div className="text-2xl font-bold text-purple-900">
62+
{formatNumber(metrics.totalAffiliates)}
63+
</div>
64+
<div className="text-sm text-purple-700">Affiliés</div>
65+
</div>
66+
67+
{/* Clics */}
68+
<div className="flex flex-col items-center p-4 bg-orange-50 rounded-lg">
69+
<MousePointer className="h-8 w-8 text-orange-600 mb-2" />
70+
<div className="text-2xl font-bold text-orange-900">
71+
{formatNumber(metrics.totalClicks)}
72+
</div>
73+
<div className="text-sm text-orange-700">Clics</div>
74+
</div>
75+
76+
{/* Revenus */}
77+
<div className="flex flex-col items-center p-4 bg-green-50 rounded-lg">
78+
<DollarSign className="h-8 w-8 text-green-600 mb-2" />
79+
<div className="text-2xl font-bold text-green-900">
80+
{formatCurrency(metrics.totalRevenue)}
81+
</div>
82+
<div className="text-sm text-green-700">Revenus</div>
83+
</div>
84+
</div>
85+
86+
{/* Métriques techniques */}
87+
<div className="mt-6 grid grid-cols-2 md:grid-cols-3 gap-4 pt-4 border-t border-gray-200">
88+
<div className="text-center">
89+
<div className="text-lg font-semibold">{metrics.avgResponseTime}ms</div>
90+
<div className="text-sm text-gray-600">Temps de réponse</div>
91+
</div>
92+
<div className="text-center">
93+
<div className="text-lg font-semibold">{metrics.activeUsers}</div>
94+
<div className="text-sm text-gray-600">Utilisateurs actifs</div>
95+
</div>
96+
<div className="text-center">
97+
<div className="text-lg font-semibold">{formatNumber(metrics.totalConversions)}</div>
98+
<div className="text-sm text-gray-600">Conversions</div>
99+
</div>
100+
</div>
101+
102+
{/* Erreurs récentes */}
103+
{metrics.recentErrors.length > 0 && (
104+
<div className="mt-6 pt-4 border-t border-gray-200">
105+
<h4 className="text-sm font-medium text-gray-900 mb-3">Erreurs récentes</h4>
106+
<div className="space-y-2 max-h-32 overflow-y-auto">
107+
{metrics.recentErrors.slice(0, 3).map((error, index) => (
108+
<div key={index} className="flex items-center gap-2 text-xs">
109+
<div className={`w-2 h-2 rounded-full ${
110+
error.severity === 'critical' ? 'bg-red-500' : 'bg-orange-500'
111+
}`} />
112+
<span className="truncate flex-1">{error.message}</span>
113+
<span className="text-gray-500">
114+
{error.timestamp.toLocaleTimeString()}
115+
</span>
116+
</div>
117+
))}
118+
</div>
119+
</div>
120+
)}
121+
</CardContent>
122+
</Card>
123+
);
124+
};

0 commit comments

Comments
 (0)