import { useState, useEffect } from "react"; import { DashboardLayout } from "./layout"; import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card"; import { Progress } from "~/components/ui/progress"; import { Badge } from "~/components/ui/badge"; import { Button } from "~/components/ui/button"; import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, LineChart, Line, } from "recharts"; import apiService from "~/lib/api"; import toast from "react-hot-toast"; import { Calendar, TrendingUp, TrendingDown, Target, Lightbulb, DollarSign, Minus, CheckCircle, Book, } from "lucide-react"; import { Tabs, TabsList, TabsTrigger, TabsContent } from "~/components/ui/tabs"; import { CustomBarChart } from "~/components/ui/custom-bar-chart"; import { DashboardCustomBarChart } from "./dashboard-custom-bar-chart"; import { InteractiveBarChart } from "./interactive-bar-chart"; import { D3ImageInfo } from "./d3-image-info"; import { Label, PolarGrid, PolarRadiusAxis, RadialBar, RadialBarChart, } from "recharts"; import { ChartContainer } from "~/components/ui/chart"; import { formatNumber } from "~/lib/utils"; import { MetricCard } from "~/components/ui/metric-card"; import { BaseCard } from "~/components/ui/base-card"; export function DashboardHome() { const [dashboardData, setDashboardData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); // Chart and schematic data from select API const [companyChartData, setCompanyChartData] = useState< { category: string; capacity: number; revenue: number; cost: number , costI : number, capacityI : number, revenueI : number }[] >([]); const [totalIncreasedCapacity, setTotalIncreasedCapacity] = useState(0); useEffect(() => { fetchDashboardData(); }, []); const fetchDashboardData = async () => { try { setLoading(true); setError(null); // Fetch top cards data const topCardsResponse = await apiService.call({ main_page_first_function: {}, }); // Fetch left section data const leftCardsResponse = await apiService.call({ main_page_second_function: {}, }); const topCardsResponseData = JSON.parse(topCardsResponse?.data); const leftCardsResponseData = JSON.parse(leftCardsResponse?.data); console.log("API Responses:", { topCardsResponseData, leftCardsResponseData, }); // Use real API data structure with English keys const topData = topCardsResponseData || {}; const leftData = leftCardsResponseData || {}; const realData = { topData: topData, leftData: leftData, chartData: leftCardsResponseData?.chartData || [], }; setDashboardData(realData); // Fetch company aggregates for chart and schematic (select API) const selectPayload = { ProcessName: "project", OutputFields: [ "related_company", "sum(pre_innovation_fee)", "sum(innovation_cost_reduction)", "sum(pre_project_production_capacity)", "sum(increased_capacity_after_innovation)", "sum(pre_project_income)", "sum(increased_income_after_innovation)", ], GroupBy: ["related_company"], }; const selectResp = await apiService.select(selectPayload); const selectDataRaw = ((): any => { try { return typeof selectResp?.data === "string" ? JSON.parse(selectResp.data) : selectResp?.data; } catch { return []; } })(); const rows: any[] = Array.isArray(selectDataRaw) ? selectDataRaw : []; let incCapacityTotal = 0; const chartRows = rows.map((r) => { const rel = r?.related_company ?? "-"; const preFee = Number(r?.pre_innovation_fee_sum ?? 0) >= 0 ? r?.pre_innovation_fee_sum : 0; const costRed = Number(r?.innovation_cost_reduction_sum ?? 0) >= 0 ? r?.innovation_cost_reduction_sum : 0; const preCap = Number(r?.pre_project_production_capacity_sum ?? 0) >= 0 ? r?.pre_project_production_capacity_sum : 0; const incCap = Number(r?.increased_capacity_after_innovation_sum ?? 0) >= 0 ? r?.increased_capacity_after_innovation_sum : 0; const preInc = Number(r?.pre_project_income_sum ?? 0) >= 0 ? r?.pre_project_income_sum : 0; const incInc = Number(r?.increased_income_after_innovation_sum ?? 0) >= 0 ? r?.increased_income_after_innovation_sum : 0; incCapacityTotal += incCap; const capacityPct = preCap >= 0 ? (incCap / preCap) * 100 : 0; const revenuePct = preInc >= 0 ? (incInc / preInc) * 100 : 0; const costPct = preFee >= 0 ? (costRed / preFee) * 100 : 0; return { category: rel, capacity: isFinite(capacityPct) ? capacityPct : 0, revenue: isFinite(revenuePct) ? revenuePct : 0, cost: isFinite(costPct) ? costPct : 0, costI : costRed, capacityI : incCap, revenueI : incInc }; }); setCompanyChartData(chartRows); setTotalIncreasedCapacity(incCapacityTotal); } catch (error) { console.error("Error fetching dashboard data:", error); const errorMessage = error instanceof Error ? error.message : "خطای نامشخص"; setError(`خطا در بارگذاری داده‌ها: ${errorMessage}`); toast.error(`خطا در بارگذاری داده‌ها: ${errorMessage}`); } finally { setLoading(false); } }; // RadialBarChart data for ideas visualization const getIdeasChartData = () => { if (!dashboardData?.topData) return [{ browser: "safari", visitors: 0, fill: "var(--color-safari)" }]; const registered = parseFloat( dashboardData.topData.registered_innovation_technology_idea || "0", ); const ongoing = parseFloat( dashboardData.topData.ongoing_innovation_technology_ideas || "0", ); const percentage = registered > 0 ? (ongoing / registered) * 100 : 0; return [ { browser: "safari", visitors: percentage, fill: "var(--color-safari)" }, ]; }; const chartData = getIdeasChartData(); const chartConfig = { visitors: { label: "Ideas Progress", }, safari: { label: "Safari", color: "var(--chart-2)", }, }; // Skeleton component for cards const SkeletonCard = ({ className = "" }) => (
); // Skeleton for the chart const SkeletonChart = () => (
{[...Array(12)].map((_, i) => (
))}
{[...Array(6)].map((_, i) => (
))}
); if (loading) { return (
{/* Top Cards Row */}
{/* Middle Section */}
{/* Chart Section */}
{/* Right Sidebar */}
); } if (error || !dashboardData) { return (

خطا در بارگذاری داده‌ها

{error || "خطای نامشخص در بارگذاری داده‌های داشبورد رخ داده است"}

); } return (
{/* Top Cards Row - Redesigned to match other components */}
{/* Ideas Card */}
0 ? Math.round( (parseFloat( dashboardData.topData ?.ongoing_innovation_technology_ideas || "0", ) / parseFloat( dashboardData.topData ?.registered_innovation_technology_idea || "1", )) * 100, ) : 0, fill: "var(--color-green)", }, ]} startAngle={90} endAngle={ 90 + ((parseFloat( dashboardData.topData ?.registered_innovation_technology_idea || "0", ) > 0 ? Math.round( (parseFloat( dashboardData.topData ?.ongoing_innovation_technology_ideas || "0", ) / parseFloat( dashboardData.topData ?.registered_innovation_technology_idea || "1", )) * 100, ) : 0) / 100) * 360 } innerRadius={35} outerRadius={55} >
ثبت شده :
{formatNumber( dashboardData.topData ?.registered_innovation_technology_idea || "0", )}
در حال اجرا :
{formatNumber( dashboardData.topData ?.ongoing_innovation_technology_ideas || "0", )}
{/* Revenue Card */} {/* Cost Reduction Card */} {/* Budget Ratio Card */}
مصوب :
{formatNumber( Math.round( parseFloat( dashboardData.topData?.approved_innovation_budget_achievement_ratio?.replace( /,/g, "", ) || "0", ), ), )}
جذب شده :
{formatNumber( Math.round( parseFloat( dashboardData.topData?.allocated_innovation_budget_achievement_ratio?.replace( /,/g, "", ) || "0", ), ), )}
{/* Main Content with Tabs */}

تحقق ارزش ها

شماتیک مقایسه ای
{ const imageMap: Record = { "بسپاران": "/besparan.png", "خوارزمی": "/khwarazmi.png", "فراورش 1": "/faravash1.png", "فراورش 2": "/faravash2.png", "کیمیا": "/kimia.png", "آب نیرو": "/abniro.png", }; return { id: item.category, name: item.category, imageUrl: imageMap[item.category] || "/placeholder.png", cost: item?.costI || 0, capacity: item?.capacityI || 0, revenue: item?.revenueI || 0, }; }) } />
{/* Left Section - Status Cards */}
{/* Technology Intensity */}
شدت فناوری
{/* Program Status */} {/* Publications */} انتشارات فناوری و نوآوری
کتاب:
{formatNumber( dashboardData.leftData?.printed_books_count || "0", )}
پتنت:
{formatNumber( dashboardData.leftData?.registered_patents_count || "0", )}
گزارش:
{formatNumber( dashboardData.leftData?.published_reports_count || "0", )}
مقاله:
{formatNumber( dashboardData.leftData?.printed_articles_count || "0", )}
{/* Promotion */} ترویج فناوری و نوآوری
کنفرانس:
{formatNumber( dashboardData.leftData?.attended_conferences_count || "0", )}
شرکت در رویداد:
{formatNumber( dashboardData.leftData?.attended_events_count || "0", )}
نمایشگاه:
{formatNumber( dashboardData.leftData?.attended_exhibitions_count || "0", )}
برگزاری رویداد:
{formatNumber( dashboardData.leftData?.organized_events_count || "0", )}
); } export default DashboardHome;