"use client"; import { useCallback, useEffect, useMemo, useState } from "react"; import Link from "next/link"; import { motion } from "motion/react"; import { Activity, AlertTriangle, ArrowRight, BarChart3, Brain, CheckCircle2, Clock3, Database, FileText, RefreshCw, Sparkles, TrendingUp, } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Card } from "@/components/ui/card"; import { getStatsAction } from "@/lib/actions/stats.action"; import { checkDeadlineNotifications } from "@/lib/actions/notification.action"; import { ContractStatusChart, ContractTypeChart, TrendChart, } from "@/components/views/dashboard/charts"; interface DashboardStats { totalContracts: number; analyzedContracts: number; processingContracts: number; uploadedContracts: number; failedContracts: number; analysisRate: number; } interface ChartData { byType: Array<{ type: string; count: number }>; byStatus: Array<{ status: string; count: number }>; trends: Array<{ date: string; count: number }>; } interface PremiumInfo { averagePremium: number; totalPremium: number; count: number; } interface RecentContract { id: string; title: string | null; type: string | null; createdAt: string; premium: number | null; } interface AILearningTelemetry { completedSamples: number; completedLast7Days: number; avgSummaryLength: number; avgExtractedTextLength: number; avgKeyPointsPerContract: number; learningScore: number; improvementHint: string; } interface StatsActionResult { success: boolean; stats?: DashboardStats; chartData?: ChartData; premiumInfo?: PremiumInfo; aiLearningTelemetry?: AILearningTelemetry; recentContracts?: RecentContract[]; error?: string; } const numberFormatter = new Intl.NumberFormat("en-US"); const currencyFormatter = new Intl.NumberFormat("en-US", { style: "currency", currency: "USD", maximumFractionDigits: 2, }); const defaultStats: DashboardStats = { totalContracts: 0, analyzedContracts: 0, processingContracts: 0, uploadedContracts: 0, failedContracts: 0, analysisRate: 0, }; const formatLastUpdated = (date: Date | null): string => { if (!date) { return "Just now"; } const seconds = Math.max(1, Math.floor((Date.now() - date.getTime()) / 1000)); if (seconds < 60) return `${seconds}s ago`; const minutes = Math.floor(seconds / 60); if (minutes < 60) return `${minutes}m ago`; const hours = Math.floor(minutes / 60); return `${hours}h ago`; }; const clampPercent = (value: number): number => Math.max(0, Math.min(100, value)); export default function DashboardPage() { const [stats, setStats] = useState(defaultStats); const [chartData, setChartData] = useState(null); const [premiumInfo, setPremiumInfo] = useState({ averagePremium: 0, totalPremium: 0, count: 0, }); const [recentContracts, setRecentContracts] = useState([]); const [aiLearningTelemetry, setAiLearningTelemetry] = useState({ completedSamples: 0, completedLast7Days: 0, avgSummaryLength: 0, avgExtractedTextLength: 0, avgKeyPointsPerContract: 0, learningScore: 0, improvementHint: "Analyze contracts to build your AI quality profile.", }); const [isLoading, setIsLoading] = useState(true); const [isRefreshing, setIsRefreshing] = useState(false); const [lastUpdated, setLastUpdated] = useState(null); const loadStats = useCallback(async (options?: { silent?: boolean }) => { const isSilentRefresh = options?.silent ?? false; if (isSilentRefresh) { setIsRefreshing(true); } else { setIsLoading(true); } try { const result = (await getStatsAction()) as StatsActionResult; if (!result.success) { return; } if (result.stats) setStats(result.stats); if (result.chartData) setChartData(result.chartData); if (result.premiumInfo) setPremiumInfo(result.premiumInfo); if (result.aiLearningTelemetry) { setAiLearningTelemetry(result.aiLearningTelemetry); } if (result.recentContracts) setRecentContracts(result.recentContracts); setLastUpdated(new Date()); } finally { if (isSilentRefresh) { setIsRefreshing(false); } else { setIsLoading(false); } } }, []); useEffect(() => { void loadStats(); // Check for upcoming contract deadlines and create notifications void checkDeadlineNotifications(); }, [loadStats]); useEffect(() => { if (stats.processingContracts === 0 && stats.uploadedContracts === 0) { return; } const intervalId = window.setInterval(() => { void loadStats({ silent: true }); }, 10000); return () => window.clearInterval(intervalId); }, [loadStats, stats.processingContracts, stats.uploadedContracts]); const hasChartData = useMemo(() => { if (!chartData) return false; const trendsCount = chartData.trends.reduce( (total, entry) => total + entry.count, 0, ); const byStatusCount = chartData.byStatus.reduce( (total, entry) => total + entry.count, 0, ); const byTypeCount = chartData.byType.reduce( (total, entry) => total + entry.count, 0, ); return trendsCount + byStatusCount + byTypeCount > 0; }, [chartData]); const pendingContracts = stats.processingContracts + stats.uploadedContracts; const analyzedPercent = stats.totalContracts > 0 ? clampPercent((stats.analyzedContracts / stats.totalContracts) * 100) : 0; const pendingPercent = stats.totalContracts > 0 ? clampPercent((pendingContracts / stats.totalContracts) * 100) : 0; const failedPercent = stats.totalContracts > 0 ? clampPercent((stats.failedContracts / stats.totalContracts) * 100) : 0; const statusRows = [ { label: "Uploaded", value: stats.uploadedContracts, colorClass: "bg-amber-500", }, { label: "Processing", value: stats.processingContracts, colorClass: "bg-primary", }, { label: "Analyzed", value: stats.analyzedContracts, colorClass: "bg-emerald-500", }, { label: "Failed", value: stats.failedContracts, colorClass: "bg-destructive", }, ]; if (isLoading) { return (
Building your analytics workspace...
); } return (

Performance Overview

Financial Contracts Analytics

A reliable command center for uploaded documents, AI analysis throughput, and portfolio quality across your BFSI workflow.

Live metrics {isRefreshing ? "Syncing..." : `Updated ${formatLastUpdated(lastUpdated)}`}

Pipeline Snapshot

{numberFormatter.format(stats.totalContracts)} files

Analyzed

{numberFormatter.format(stats.analyzedContracts)}

Pending

{numberFormatter.format(pendingContracts)}

Total Files

{numberFormatter.format(stats.totalContracts)}

Uploaded into your workspace

Analyzed

{numberFormatter.format(stats.analyzedContracts)}

Completed by AI pipeline

Pending Queue

{numberFormatter.format(pendingContracts)}

Uploaded and processing files

Failed

{numberFormatter.format(stats.failedContracts)}

Items needing re-analysis

Pipeline Pulse

{statusRows.map((row) => { const rowPercent = stats.totalContracts > 0 ? clampPercent((row.value / stats.totalContracts) * 100) : 0; return (

{row.label}

{numberFormatter.format(row.value)}

); })}

Success Rate

{stats.analysisRate}%

Completed vs total files

Avg Premium

{currencyFormatter.format(premiumInfo.averagePremium)}

Across {numberFormatter.format(premiumInfo.count)} analyzed files

Total Premium

{currencyFormatter.format(premiumInfo.totalPremium)}

Portfolio value captured by AI

AI Learning Telemetry

Score {aiLearningTelemetry.learningScore}/100

Completed Samples

{numberFormatter.format(aiLearningTelemetry.completedSamples)}

{numberFormatter.format(aiLearningTelemetry.completedLast7Days)}{" "} in last 7 days

Avg Summary Length

{numberFormatter.format(aiLearningTelemetry.avgSummaryLength)}

characters

Avg Extracted Text

{numberFormatter.format( aiLearningTelemetry.avgExtractedTextLength, )}

characters

Avg Key Points

{aiLearningTelemetry.avgKeyPointsPerContract.toFixed(1)}

items per analysis

Learning quality index {aiLearningTelemetry.learningScore}%

{aiLearningTelemetry.improvementHint}

{hasChartData ? (
{chartData && chartData.trends.length > 0 && (

Upload Trend (30 days)

)} {chartData && chartData.byStatus.length > 0 && (

Processing Status

({ ...s, name: s.status, }))} />
)} {chartData && chartData.byType.length > 0 && (

Contract Type Distribution

)}

Recent Analyses

{recentContracts.length > 0 ? (
{recentContracts.map((contract) => (

{contract.title || "Untitled contract"}

{contract.type || "Unknown type"} {new Date(contract.createdAt).toLocaleDateString( "en-US", { month: "short", day: "numeric", }, )}

Premium:{" "} {contract.premium !== null ? currencyFormatter.format(contract.premium) : "Not detected"}

))}
) : (

No recent analyses yet

Analyze a contract to populate this activity feed.

)}
) : (

Your analytics will appear here

Upload and analyze contracts to unlock trend and distribution charts.

)}
); }