Update dashboard to show accurate statistics and improve sidebar functionality

Refactor the API endpoint for statistics to accurately calculate and display scheduled posts, AI text generations, and media stored, including percentage changes and trending indicators.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: ae4037a0-2a6f-4530-9bac-79b543286bda
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/397bca8c-984f-43ff-841a-10897aeb8140/ae4037a0-2a6f-4530-9bac-79b543286bda/ycYcQjF
This commit is contained in:
michaelschal committed 2025-10-08 15:35:49 +00:00
1 parent 387e390cb8
commit 48138c2166
2 files changed
+61 -10

No files matched your search

+20 -9
View File
@@ -1,8 +1,19 @@
import { CalendarCheck, Users, Bot, Images, TrendingUp, TrendingDown } from "lucide-react";
import { useQuery } from "@tanstack/react-query";
interface StatsResponse {
scheduledPosts: number;
scheduledPostsChange?: string;
scheduledPostsTrending?: "up" | "down";
connectedPages: number;
aiTextsGenerated: number;
aiTextsChange?: string;
aiTextsTrending?: "up" | "down";
mediaStored: number;
}
export default function StatsCards() {
const { data: stats, isLoading } = useQuery({
const { data: stats, isLoading } = useQuery<StatsResponse>({
queryKey: ["/api/stats"],
});
@@ -10,32 +21,32 @@ export default function StatsCards() {
{
icon: CalendarCheck,
iconColor: "from-blue-500 to-blue-600",
title: (stats as any)?.scheduledPosts ?? 0,
title: stats?.scheduledPosts ?? 0,
subtitle: "Publications planifiées",
change: "+12%",
trending: "up",
change: stats?.scheduledPostsChange,
trending: stats?.scheduledPostsTrending,
changeLabel: "vs mois dernier",
},
{
icon: Users,
iconColor: "from-purple-500 to-purple-600",
title: (stats as any)?.connectedPages ?? 0,
title: stats?.connectedPages ?? 0,
subtitle: "Pages connectées",
info: "Facebook • Instagram",
},
{
icon: Bot,
iconColor: "from-green-500 to-green-600",
title: (stats as any)?.aiTextsGenerated ?? 0,
title: stats?.aiTextsGenerated ?? 0,
subtitle: "Textes générés par IA",
change: "+8%",
trending: "up",
change: stats?.aiTextsChange,
trending: stats?.aiTextsTrending,
changeLabel: "vs hier",
},
{
icon: Images,
iconColor: "from-cyan-500 to-cyan-600",
title: (stats as any)?.mediaStored ?? 0,
title: stats?.mediaStored ?? 0,
subtitle: "Médias stockés",
info: "Images • Vidéos",
},
+41 -1
View File
@@ -369,12 +369,52 @@ export async function registerRoutes(app: Express): Promise<Server> {
const media = await storage.getMedia(userId);
const aiGenerations = await storage.getAiGenerations(userId);
// Statistiques actuelles
const scheduledPosts = posts.filter(p => p.status === "scheduled").length;
const currentAiTexts = aiGenerations.length;
const currentMedia = media.length;
// Calculer les statistiques de la période précédente (hier pour les textes IA, mois dernier pour les posts)
const now = new Date();
const yesterday = new Date(now);
yesterday.setDate(yesterday.getDate() - 1);
yesterday.setHours(0, 0, 0, 0);
const lastMonth = new Date(now);
lastMonth.setMonth(lastMonth.getMonth() - 1);
// Textes IA générés hier
const aiTextsYesterday = aiGenerations.filter(gen => {
if (!gen.createdAt) return false;
const genDate = new Date(gen.createdAt);
genDate.setHours(0, 0, 0, 0);
return genDate.getTime() === yesterday.getTime();
}).length;
// Posts planifiés le mois dernier
const scheduledPostsLastMonth = posts.filter(p => {
if (!p.createdAt) return false;
const createdDate = new Date(p.createdAt);
return p.status === "scheduled" && createdDate < lastMonth;
}).length;
// Calculer les variations en pourcentage
const aiTextChange = aiTextsYesterday > 0
? Math.round(((currentAiTexts - aiTextsYesterday) / aiTextsYesterday) * 100)
: currentAiTexts > 0 ? 100 : 0;
const scheduledPostsChange = scheduledPostsLastMonth > 0
? Math.round(((scheduledPosts - scheduledPostsLastMonth) / scheduledPostsLastMonth) * 100)
: scheduledPosts > 0 ? 100 : 0;
res.json({
scheduledPosts,
scheduledPostsChange: scheduledPostsChange > 0 ? `+${scheduledPostsChange}%` : `${scheduledPostsChange}%`,
scheduledPostsTrending: scheduledPostsChange >= 0 ? "up" : "down",
connectedPages: pages.length,
aiTextsGenerated: aiGenerations.length,
aiTextsGenerated: currentAiTexts,
aiTextsChange: aiTextChange > 0 ? `+${aiTextChange}%` : `${aiTextChange}%`,
aiTextsTrending: aiTextChange >= 0 ? "up" : "down",
mediaStored: media.length,
});
} catch (error) {