mirror of
https://github.com/R0m1k3/Socialflow.git
synced 2026-10-11 17:26:45 +02:00
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:
1 parent
387e390cb8
commit
48138c2166
2 files changed
+61
-10
No files matched your search
@@ -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
@@ -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) {
|
||||
|
||||
Reference in new issue
Block a user