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;