Files
edr-platform/apps/edr-freight-web/backoffice/src/shared/components/activity-log/activity-stats.tsx
2026-07-10 10:41:48 +03:00

126 lines
4.1 KiB
TypeScript

import { Card, CardContent } from "@/shared/common/ui/card";
import {
Activity,
CheckCircle,
XCircle,
Clock,
TrendingUp,
} from "lucide-react";
import { cn } from "@/shared/lib/utils";
import { useTranslation } from "react-i18next";
interface ActivityStatsProps {
totalActivities: number;
successRate: number;
avgDailyActivities: number;
uniqueUsers: number;
topActions: { action: string; count: number }[];
}
export function ActivityStats({
totalActivities,
successRate,
avgDailyActivities,
uniqueUsers,
topActions,
}: ActivityStatsProps) {
const border = "border-gray-200 dark:border-gray-800";
const surface = "bg-white dark:bg-gray-900";
const textStrong = "text-gray-900 dark:text-gray-100";
const textMuted = "text-gray-600 dark:text-gray-300";
const textSubtle = "text-gray-500 dark:text-gray-400";
const textSubtler = "text-gray-400 dark:text-gray-500";
const iconBgLight = "bg-gray-100 dark:bg-gray-800";
const { t } = useTranslation();
const stats = [
{
label: t("auditLog.stats.totalActivities"),
value: totalActivities.toLocaleString(),
icon: Activity,
color: "text-blue-600 dark:text-blue-400",
bgColor: "bg-blue-50 dark:bg-blue-950",
},
{
label: t("auditLog.stats.successRate"),
value: `${successRate}%`,
icon: CheckCircle,
color: "text-green-600 dark:text-green-400",
bgColor: "bg-green-50 dark:bg-green-950",
},
{
label: t("auditLog.stats.dailyAverage"),
value: avgDailyActivities.toLocaleString(),
icon: TrendingUp,
color: "text-purple-600 dark:text-purple-400",
bgColor: "bg-purple-50 dark:bg-purple-950",
},
{
label: t("auditLog.stats.uniqueUsers"),
value: uniqueUsers.toLocaleString(),
icon: Clock,
color: "text-orange-600 dark:text-orange-400",
bgColor: "bg-orange-50 dark:bg-orange-950",
},
];
return (
<div className="space-y-6">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
{stats.map((stat, index) => (
<Card key={index} className={cn(border, surface)}>
<CardContent className="p-6">
<div className="flex items-center justify-between">
<div>
<p className={cn("text-sm font-medium", textMuted)}>
{stat.label}
</p>
<p className={cn("text-2xl font-bold mt-1", textStrong)}>
{stat.value}
</p>
</div>
<div className={cn("p-3 rounded-full", stat.bgColor)}>
<stat.icon className={cn("h-6 w-6", stat.color)} />
</div>
</div>
</CardContent>
</Card>
))}
</div>
<Card className={cn(border, surface)}>
<CardContent className="p-6">
<h3 className={cn("text-lg font-semibold mb-4", textStrong)}>
{t("auditLog.stats.topActions")}
</h3>
<div className="space-y-3">
{topActions.map((action, index) => (
<div key={index} className="flex items-center justify-between">
<div className="flex items-center gap-3">
<div
className={cn(
"w-8 h-8 rounded-md flex items-center justify-center",
iconBgLight,
)}>
<span className={cn("text-sm font-medium", textSubtle)}>
{action.action.charAt(0)}
</span>
</div>
<span className={cn("text-sm font-medium", textStrong)}>
{t(`activityLogPage.actions.${action.action}`, {
defaultValue: action.action,
})}
</span>
</div>
<span className={cn("text-sm font-semibold", textMuted)}>
{action.count} {t("auditLog.stats.times")}
</span>
</div>
))}
</div>
</CardContent>
</Card>
</div>
);
}