Qassure-frontend/src/features/dashboard/components/StatsGrid.tsx

127 lines
3.8 KiB
TypeScript

import { useState, useEffect } from "react";
import {
Building2,
CheckCircle2,
// Users,
// TrendingUp,
Package,
Heart,
} from "lucide-react";
import { StatCard } from "./StatCard";
import type { StatCardData } from "@/types/dashboard";
import { dashboardService } from "@/services/dashboard-service";
export const StatsGrid = () => {
const [statsData, setStatsData] = useState<StatCardData[]>([]);
const [isLoading, setIsLoading] = useState<boolean>(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
const fetchStatistics = async () => {
try {
setIsLoading(true);
setError(null);
const response = await dashboardService.getStatistics();
const { data } = response;
const mappedStats: StatCardData[] = [
{
icon: Building2,
value: data.totalTenants,
label: "Total Tenants",
badge: { text: `${data.activeTenants} active`, variant: "green" },
},
{
icon: CheckCircle2,
value: data.activeTenants,
label: "Active Tenants",
badge: {
text:
data.totalTenants > 0
? `${Math.round((data.activeTenants / data.totalTenants) * 100)}% Rate`
: "0% Rate",
variant: "green",
},
},
// {
// icon: Users,
// value: data.totalUsers,
// label: "Total Users",
// badge: { text: "All users", variant: "gray" },
// },
// {
// icon: TrendingUp,
// value: data.activeSessions,
// label: "Active Sessions",
// badge: { text: "Live now", variant: "gray" },
// },
{
icon: Package,
value: data.registeredModules,
label: "Registered Modules",
badge: { text: "Total", variant: "gray" },
},
{
icon: Heart,
value: data.healthyModules,
label: "Healthy Modules",
badge: {
text:
data.registeredModules > 0
? `${Math.round((data.healthyModules / data.registeredModules) * 100)}% Uptime`
: "0% Uptime",
variant:
data.healthyModules === data.registeredModules &&
data.registeredModules > 0
? "green"
: "gray",
},
},
];
setStatsData(mappedStats);
} catch (err) {
console.error("Failed to fetch dashboard statistics:", err);
setError("Failed to load statistics. Please try again.");
} finally {
setIsLoading(false);
}
};
fetchStatistics();
}, []);
if (isLoading) {
return (
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 md:gap-6 mb-4 md:mb-6 auto-rows-fr">
{Array.from({ length: 6 }).map((_, index) => (
<div
key={index}
className="bg-white border border-[rgba(0,0,0,0.08)] rounded-lg p-[17px] flex flex-col gap-3 h-[107px] animate-pulse"
>
<div className="h-4 bg-gray-200 rounded w-1/4"></div>
<div className="h-8 bg-gray-200 rounded w-1/2"></div>
<div className="h-3 bg-gray-200 rounded w-1/3"></div>
</div>
))}
</div>
);
}
if (error) {
return (
<div className="bg-red-50 border border-red-200 rounded-lg p-4 mb-4 md:mb-6">
<p className="text-red-800 text-sm">{error}</p>
</div>
);
}
return (
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 md:gap-6 mb-4 md:mb-6 auto-rows-fr">
{statsData.map((stat, index) => (
<StatCard key={index} data={stat} />
))}
</div>
);
};