import { Layout } from "@/components/layout/Layout"; import type { ReactElement } from "react"; import { FileCheck, Briefcase, FileText, Users, Bell } from "lucide-react"; import { QuickActions } from "@/features/dashboard/components/QuickActions"; import { RecentActivity } from "@/features/dashboard/components/RecentActivity"; import { cn } from "@/lib/utils"; import { useState, useEffect } from "react"; import { useAppTheme } from "@/hooks/useAppTheme"; import { workflowService } from "@/services/workflow-service"; import { dashboardService, type TenantDashboardStats, } from "@/services/dashboard-service"; import type { WorkflowTask } from "@/types/workflow"; import { useNavigate } from "react-router-dom"; import { GradientStatCard } from "@/components/shared"; import type { LucideIcon } from "lucide-react"; interface StatCardProps { icon: LucideIcon; value: string | number; label: string; badge?: { text: string; variant: "success" | "warning" | "info" | "error"; }; } const TaskCard = ({ task }: { task: WorkflowTask }) => { const navigate = useNavigate(); const formatDeadline = (dueDate: string) => { const now = new Date(); const due = new Date(dueDate); const diffTime = due.getTime() - now.getTime(); const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)); if (diffDays === 0) return "Due today"; if (diffDays === 1) return "Tomorrow"; if (diffDays < 0) return "Overdue"; return `In ${diffDays} Days`; }; const handleView = () => { if (task.entity.type.toLowerCase() === "document") { navigate(`/tenant/documents/${task.entity.id}`); } }; return (
{task.entity.type} {formatDeadline(task.due_at)}
{task.entity.name}
{task.step.name} •{" "} {task.assignment?.assigned_to_name || (task.assignment?.assigned_role_ids?.length ? `${task.assignment.assigned_role_ids.length} roles` : "Unassigned")}
); }; const Dashboard = (): ReactElement => { const navigate = useNavigate(); const { primaryColor } = useAppTheme(); const [tasks, setTasks] = useState([]); const [tasksLoading, setTasksLoading] = useState(true); const [stats, setStats] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { fetchDashboardData(); }, []); const fetchDashboardData = async () => { setLoading(true); setTasksLoading(true); try { // Fetch tasks independently workflowService .listTasks({ limit: 3 }) .then((response) => { if (response.success && Array.isArray(response.data)) { setTasks(response.data); } }) .catch((error) => { console.error("Error fetching tasks:", error); }) .finally(() => { setTasksLoading(false); }); // Fetch statistics independently dashboardService .getTenantStatistics() .then((response) => { if (response.success) { setStats(response.data); } }) .catch((error) => { console.error("Error fetching dashboard statistics:", error); }) .finally(() => { setLoading(false); }); } catch (error) { console.error("Critical error in fetchDashboardData:", error); setLoading(false); setTasksLoading(false); } }; const statCards: StatCardProps[] = [ stats?.documentsCount !== undefined && { icon: FileText, value: stats.documentsCount, label: "Total Documents", badge: { text: "Controlled", variant: "info" }, }, stats?.pendingTasks !== undefined && { icon: FileCheck, value: stats.pendingTasks, label: "My Tasks", badge: { text: "Action Needed", variant: "warning" }, }, stats?.usersCount !== undefined && { icon: Users, value: stats.usersCount, label: "Total Users", badge: { text: "Team Members", variant: "success" }, }, stats?.unreadNotificationsCount !== undefined && { icon: Bell, value: stats.unreadNotificationsCount, label: "Notifications", badge: { text: "Unread", variant: "error" }, }, stats?.activeModulesCount !== undefined && { icon: Briefcase, value: stats.activeModulesCount, label: "Running Modules", badge: { text: "Operational", variant: "success" }, }, ].filter(Boolean) as StatCardProps[]; return (
{/* Main Content Area (Left) */}
{/* Stats Grid */}
{loading ? (
Loading statistics...
) : statCards.length > 0 ? ( statCards.map((card, index) => ( )) ) : (
No statistics available
)}
{/* Recent Activity Card */}
{/* Sidebar area (Right) */}
{/* My Tasks Card */}

My Tasks

{tasksLoading ? (
Loading tasks...
) : tasks.length > 0 ? ( tasks.map((task) => ) ) : (
No pending tasks
)}
); }; export default Dashboard;