mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 04:08:11 +00:00
159 lines
5.5 KiB
TypeScript
159 lines
5.5 KiB
TypeScript
import React from "react";
|
|
import { Button } from "@/shared/common/ui/button";
|
|
import {
|
|
Card,
|
|
CardContent,
|
|
CardHeader,
|
|
CardTitle,
|
|
} from "@/shared/common/ui/card";
|
|
import { ActivityTimeline } from "@/super-admin/components/dashboard/components/ActivityTimeline";
|
|
import { OrgTable } from "@/super-admin/components/dashboard/components/OrgTable";
|
|
import { StatCard } from "@/super-admin/components/dashboard/components/StatCard";
|
|
import { Link, useNavigate } from "react-router-dom";
|
|
import { Plus, Loader2, AlertCircle } from "lucide-react";
|
|
import { useOrganizations } from "@/super-admin/hooks/useOrganizations";
|
|
import { useTranslation } from "react-i18next";
|
|
import SmartOfficeAuditPage from "@/record-management/pages/AuditLog/SmartOfficeAuditPage";
|
|
|
|
const DashboardPage = () => {
|
|
const navigate = useNavigate();
|
|
const pageSize = 10;
|
|
const { t } = useTranslation();
|
|
const { organizationsResponse, isLoading, isError, refetch } =
|
|
useOrganizations("Org", {
|
|
take: pageSize,
|
|
orderBy: "createdAt",
|
|
order: "createdAt:Desc",
|
|
});
|
|
|
|
const {
|
|
organizationsAdminsResponse,
|
|
isLoading: isLoadingAdmins,
|
|
isError: isAdminError,
|
|
refetch: refetchAdmins,
|
|
} = useOrganizations("Admin", {
|
|
take: pageSize,
|
|
orderBy: "updatedAt",
|
|
order: "updatedAt: DESC",
|
|
});
|
|
|
|
if (isLoading || isLoadingAdmins) {
|
|
return (
|
|
<div className="p-6 flex items-center justify-center h-64">
|
|
<div className="flex flex-col items-center gap-2">
|
|
<Loader2 className="h-8 w-8 animate-spin text-primary" />
|
|
<div className="text-sm text-muted-foreground">
|
|
Loading dashboard...
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (isError || isAdminError) {
|
|
return (
|
|
<div className="p-6 flex items-center justify-center h-64">
|
|
<div className="flex flex-col items-center gap-4">
|
|
<AlertCircle className="h-12 w-12 text-red-500" />
|
|
<div className="text-red-500 font-medium">
|
|
Error loading dashboard
|
|
</div>
|
|
<p className="text-gray-500 dark:text-gray-400 text-center max-w-md mb-4">
|
|
There was an issue loading the dashboard data. This could be due to
|
|
network issues or server problems.
|
|
</p>
|
|
<Button
|
|
onClick={() => {
|
|
refetch();
|
|
refetchAdmins();
|
|
}}
|
|
className="bg-primary hover:bg-primary/90 text-primary-foreground">
|
|
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
|
{t("organization.retry")}
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="p-6 space-y-10">
|
|
{/* Stat Cards */}
|
|
<Card className="col-span-2 shadow-none border-none bg-transparent px-0">
|
|
<CardHeader className="flex flex-row justify-between items-center px-0">
|
|
<CardTitle className="text-xl font-semibold">
|
|
{t("organization.statistics")}
|
|
</CardTitle>
|
|
<Link to="/user-management/organizations/new">
|
|
<Button className="bg-primary hover:bg-primary/90 text-primary-foreground px-5 py-2 rounded-md text-sm font-medium shadow-md">
|
|
<Plus className="w-4 h-4 mr-2" />
|
|
{t("organization.newOrganization")}
|
|
</Button>
|
|
</Link>
|
|
</CardHeader>
|
|
<CardContent className="px-0">
|
|
<section className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
|
<StatCard
|
|
title={t("organization.totalOrganizations")}
|
|
value={organizationsResponse?.count || 0}
|
|
// indicator={`${0}% ↑`}
|
|
color="text-primary-500"
|
|
icon="building"
|
|
variant="primary"
|
|
onClick={() => {
|
|
navigate("/user-management/organizations");
|
|
}}
|
|
/>
|
|
{/* <StatCard
|
|
title="Pending Requests"
|
|
value={stats.pendingRequests}
|
|
indicator={`${stats.percentChanges.pending}% ↓`}
|
|
color="text-red-500"
|
|
icon="clock"
|
|
variant="default"
|
|
/> */}
|
|
<StatCard
|
|
title={t("organization.organizationAdmins")}
|
|
value={organizationsAdminsResponse?.count || 0}
|
|
// indicator={`${0}% ↓`}
|
|
color="text-red-500"
|
|
icon="user"
|
|
variant="default"
|
|
onClick={() => {
|
|
navigate("/user-management/organization_admins");
|
|
}}
|
|
/>
|
|
</section>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
{/* Table and Activities */}
|
|
<section className="grid grid-cols-1 md:grid-cols-[2fr_1fr] gap-4">
|
|
<Card className="min-w-0 shadow-none border-none bg-transparent px-0">
|
|
<SmartOfficeAuditPage />
|
|
</Card>
|
|
<Card className=" min-w-0 shadow-none border-none bg-transparent px-0">
|
|
<CardHeader className="flex flex-row justify-between items-center px-0">
|
|
<CardTitle className="text-base font-semibold">
|
|
{t("organization.recentOrganizations")}
|
|
</CardTitle>
|
|
<Link to="/organizations">
|
|
<Button
|
|
variant="link"
|
|
className="text-primary dark:text-primary-400 text-sm px-0">
|
|
{t("organization.viewMore")}
|
|
</Button>
|
|
</Link>
|
|
</CardHeader>
|
|
|
|
<CardContent className="px-0 overflow-x-auto">
|
|
<OrgTable organizations={organizationsResponse?.items || []} />
|
|
</CardContent>
|
|
</Card>
|
|
</section>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default DashboardPage;
|