fix styles in cards

This commit is contained in:
Saeed AB 2025-08-27 18:54:36 +03:30
parent 676e3b5cf6
commit cc5ee070e0
2 changed files with 708 additions and 339 deletions

View File

@ -0,0 +1,74 @@
import React from "react";
import { formatNumber } from "~/lib/utils";
interface DataItem {
label: string;
value: number;
color: string;
}
interface DashboardCustomBarChartProps {
title: string;
data: DataItem[];
loading?: boolean;
}
export function DashboardCustomBarChart({
title,
data,
loading = false,
}: DashboardCustomBarChartProps) {
if (loading) {
return (
<div className="w-full">
<h3 className="text-lg font-bold text-white font-persian mb-4 text-center border-b-2 border-gray-500/20 pb-3">
{title}
</h3>
<div className="space-y-3">
{[1, 2, 3].map((i) => (
<div key={i} className="animate-pulse">
<div className="h-12 bg-gray-600/30 rounded-lg"></div>
</div>
))}
</div>
</div>
);
}
// Calculate the maximum value for scaling
const maxValue = Math.max(...data.map((item) => item.value));
return (
<div className="w-full">
<h3 className="text-lg font-bold text-white font-persian mb-4 text-center border-b-2 border-gray-500/20">
{title}
</h3>
<div className="px-4">
{data.map((item, index) => {
const widthPercentage =
maxValue > 0 ? (item.value / maxValue) * 100 : 0;
return (
<div key={index} className="relative">
{/* Bar container */}
<div className="relative min-h-6 h-10 rounded-lg overflow-hidden">
{/* Animated bar */}
<div
className={`absolute left-0 h-auto top-0 ${item.color} rounded-lg transition-all duration-1000 ease-out flex items-center justify-between px-2`}
style={{ width: `${widthPercentage}%` }}
>
<span className="text-white font-bold text-base">
{formatNumber(item.value)}
</span>
<span className="text-white font-persian font-medium text-sm w-max">
{item.label}
</span>
</div>
</div>
</div>
);
})}
</div>
</div>
);
}

View File

@ -4,23 +4,43 @@ import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card";
import { Progress } from "~/components/ui/progress"; import { Progress } from "~/components/ui/progress";
import { Badge } from "~/components/ui/badge"; import { Badge } from "~/components/ui/badge";
import { Button } from "~/components/ui/button"; import { Button } from "~/components/ui/button";
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, LineChart, Line } from 'recharts'; import {
BarChart,
Bar,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
ResponsiveContainer,
LineChart,
Line,
} from "recharts";
import apiService from "~/lib/api"; import apiService from "~/lib/api";
import toast from "react-hot-toast"; import toast from "react-hot-toast";
import { Calendar, TrendingUp, TrendingDown, Target, Lightbulb, DollarSign, Minus, CheckCircle, BookOpen } from "lucide-react"; import {
Calendar,
TrendingUp,
TrendingDown,
Target,
Lightbulb,
DollarSign,
Minus,
CheckCircle,
BookOpen,
} from "lucide-react";
import { Tabs, TabsList, TabsTrigger, TabsContent } from "~/components/ui/tabs"; import { Tabs, TabsList, TabsTrigger, TabsContent } from "~/components/ui/tabs";
import { CustomBarChart } from "~/components/ui/custom-bar-chart"; import { CustomBarChart } from "~/components/ui/custom-bar-chart";
import { DashboardCustomBarChart } from "./dashboard-custom-bar-chart";
import { import {
Label, Label,
PolarGrid, PolarGrid,
PolarRadiusAxis, PolarRadiusAxis,
RadialBar, RadialBar,
RadialBarChart, RadialBarChart,
} from "recharts" } from "recharts";
import { ChartContainer } from "~/components/ui/chart" import { ChartContainer } from "~/components/ui/chart";
import { formatNumber } from "~/lib/utils"; import { formatNumber } from "~/lib/utils";
export function DashboardHome() { export function DashboardHome() {
const [dashboardData, setDashboardData] = useState<any | null>(null); const [dashboardData, setDashboardData] = useState<any | null>(null);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
@ -36,25 +56,28 @@ export function DashboardHome() {
setError(null); setError(null);
// First authenticate if needed // First authenticate if needed
const token = localStorage.getItem('auth_token'); const token = localStorage.getItem("auth_token");
if (!token) { if (!token) {
await apiService.login('inogen_admin', '123456'); await apiService.login("inogen_admin", "123456");
} }
// Fetch top cards data // Fetch top cards data
const topCardsResponse = await apiService.call({ const topCardsResponse = await apiService.call({
main_page_first_function: {} main_page_first_function: {},
}); });
// Fetch left section data // Fetch left section data
const leftCardsResponse = await apiService.call({ const leftCardsResponse = await apiService.call({
main_page_second_function: {} main_page_second_function: {},
}); });
const topCardsResponseData = JSON.parse(topCardsResponse?.data); const topCardsResponseData = JSON.parse(topCardsResponse?.data);
const leftCardsResponseData = JSON.parse(leftCardsResponse?.data); const leftCardsResponseData = JSON.parse(leftCardsResponse?.data);
console.log('API Responses:', { topCardsResponseData, leftCardsResponseData }); console.log("API Responses:", {
topCardsResponseData,
leftCardsResponseData,
});
// Use real API data structure with English keys // Use real API data structure with English keys
const topData = topCardsResponseData || {}; const topData = topCardsResponseData || {};
@ -62,12 +85,13 @@ export function DashboardHome() {
const realData = { const realData = {
topData: topData, topData: topData,
leftData: leftData, leftData: leftData,
chartData: leftCardsResponseData?.chartData || [] chartData: leftCardsResponseData?.chartData || [],
}; };
setDashboardData(realData); setDashboardData(realData);
} catch (error) { } catch (error) {
console.error('Error fetching dashboard data:', error); console.error("Error fetching dashboard data:", error);
const errorMessage = error instanceof Error ? error.message : 'خطای نامشخص'; const errorMessage =
error instanceof Error ? error.message : "خطای نامشخص";
setError(`خطا در بارگذاری داده‌ها: ${errorMessage}`); setError(`خطا در بارگذاری داده‌ها: ${errorMessage}`);
toast.error(`خطا در بارگذاری داده‌ها: ${errorMessage}`); toast.error(`خطا در بارگذاری داده‌ها: ${errorMessage}`);
} finally { } finally {
@ -77,18 +101,26 @@ export function DashboardHome() {
// RadialBarChart data for ideas visualization // RadialBarChart data for ideas visualization
const getIdeasChartData = () => { const getIdeasChartData = () => {
if (!dashboardData?.topData) return [{ browser: "safari", visitors: 0, fill: "var(--color-safari)" }]; if (!dashboardData?.topData)
return [{ browser: "safari", visitors: 0, fill: "var(--color-safari)" }];
const registered = parseFloat(dashboardData.topData.registered_innovation_technology_idea || '0'); const registered = parseFloat(
const ongoing = parseFloat(dashboardData.topData.ongoing_innovation_technology_ideas || '0'); dashboardData.topData.registered_innovation_technology_idea || "0",
const percentage = registered > 0 ? Math.round((ongoing / registered) * 100) : 0; );
const ongoing = parseFloat(
dashboardData.topData.ongoing_innovation_technology_ideas || "0",
);
const percentage =
registered > 0 ? Math.round((ongoing / registered) * 100) : 0;
return [{ browser: "safari", visitors: percentage, fill: "var(--color-safari)" }]; return [
{ browser: "safari", visitors: percentage, fill: "var(--color-safari)" },
];
}; };
const chartData = getIdeasChartData(); const chartData = getIdeasChartData();
const chartConfig = { const chartConfig = {
visitors: { visitors: {
label: "Ideas Progress", label: "Ideas Progress",
}, },
@ -96,13 +128,12 @@ const chartConfig = {
label: "Safari", label: "Safari",
color: "var(--chart-2)", color: "var(--chart-2)",
}, },
}; };
if (loading) { if (loading) {
return ( return (
<DashboardLayout> <DashboardLayout>
<div className="p-6"> <div className="">
<div className="flex items-center justify-center h-64"> <div className="flex items-center justify-center h-64">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-500"></div> <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-500"></div>
</div> </div>
@ -114,9 +145,9 @@ const chartConfig = {
if (error || !dashboardData) { if (error || !dashboardData) {
return ( return (
<DashboardLayout> <DashboardLayout>
<div className="p-6"> <div className="">
<Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm border-red-500/50"> <Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm border-red-500/50">
<CardContent className="p-6"> <CardContent className="">
<div className="flex flex-col items-center justify-center space-y-4"> <div className="flex flex-col items-center justify-center space-y-4">
<div className="p-4 bg-red-500/20 rounded-full"> <div className="p-4 bg-red-500/20 rounded-full">
<CheckCircle className="w-12 h-12 text-red-400" /> <CheckCircle className="w-12 h-12 text-red-400" />
@ -125,7 +156,8 @@ const chartConfig = {
خطا در بارگذاری دادهها خطا در بارگذاری دادهها
</h3> </h3>
<p className="text-gray-300 text-center max-w-md"> <p className="text-gray-300 text-center max-w-md">
{error || 'خطای نامشخص در بارگذاری داده‌های داشبورد رخ داده است'} {error ||
"خطای نامشخص در بارگذاری داده‌های داشبورد رخ داده است"}
</p> </p>
<Button <Button
onClick={fetchDashboardData} onClick={fetchDashboardData}
@ -142,8 +174,6 @@ const chartConfig = {
); );
} }
return ( return (
<DashboardLayout> <DashboardLayout>
<div className="p-3 pb-0 grid grid-cols-3 gap-4"> <div className="p-3 pb-0 grid grid-cols-3 gap-4">
@ -151,51 +181,148 @@ const chartConfig = {
<div className="flex justify-between gap-6 [&>*]:w-full col-span-3"> <div className="flex justify-between gap-6 [&>*]:w-full col-span-3">
{/* Ideas Card */} {/* Ideas Card */}
<Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm border-gray-700/50"> <Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm border-gray-700/50">
<CardContent className="p-4"> <CardContent className="py-4 px-0">
<div className="flex flex-col justify-between gap-2"> <div className="flex flex-col justify-between gap-2">
<div className="flex justify-between items-center border-b-2 mx-4 border-gray-500/20"> <div className="flex justify-between items-center border-b-2 border-gray-500/20 pb-2">
<h3 className="text-lg font-bold text-white font-persian py-2"> <h3 className="text-lg font-bold text-white font-persian px-6">
ایدههای فناوری و نوآوری ایدههای فناوری و نوآوری
</h3> </h3>
</div> </div>
<div className="flex items-center gap-2 justify-center flex-row-reverse p-1"> <div className="flex items-center gap-2 justify-center flex-row-reverse">
<ChartContainer config={chartConfig} className="w-full h-full max-h-20 max-w-40"> <ChartContainer
<RadialBarChart data={chartData} startAngle={0} endAngle={250} innerRadius={30} outerRadius={50}> config={chartConfig}
className="w-full h-full max-h-20 max-w-40"
>
<RadialBarChart
data={[
{
browser: "ideas",
visitors:
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,
fill: "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}
>
<PolarGrid <PolarGrid
gridType="circle" gridType="circle"
radialLines={false} radialLines={false}
stroke="none" stroke="none"
className="first:fill-muted last:fill-background" className="first:fill-red-400 last:fill-background"
polarRadius={[36, 24]} polarRadius={[38, 31]}
/> />
<RadialBar dataKey="visitors" background cornerRadius={5} /> <RadialBar
<PolarRadiusAxis tick={false} tickLine={false} axisLine={false}> dataKey="visitors"
background
cornerRadius={5}
/>
<PolarRadiusAxis
tick={false}
tickLine={false}
axisLine={false}
>
<Label <Label
content={({ viewBox }) => { content={({ viewBox }) => {
if (viewBox && "cx" in viewBox && "cy" in viewBox) { if (viewBox && "cx" in viewBox && "cy" in viewBox) {
return ( return (
<text x={viewBox.cx} y={viewBox.cy} textAnchor="middle" dominantBaseline="middle"> <text
<tspan x={viewBox.cx} y={viewBox.cy} className="fill-foreground text-lg font-bold"> x={viewBox.cx}
{formatNumber(dashboardData.topData?.ongoing_innovation_technology_ideas || '0')}% y={viewBox.cy}
</tspan> textAnchor="middle"
dominantBaseline="middle"
</text> >
<tspan
x={viewBox.cx}
y={viewBox.cy}
className="fill-foreground text-lg font-bold"
>
%
{formatNumber(
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,
)}
</tspan>
</text>
);
} }
}} }}
/> />
</PolarRadiusAxis> </PolarRadiusAxis>
</RadialBarChart> </RadialBarChart>
</ChartContainer> </ChartContainer>
<div className="font-bold font-persian text-center mt-2"> <div className="font-bold font-persian text-center">
<div className="flex flex-col justify-between items-center"> <div className="flex flex-col justify-between items-center gap-2">
<span className="flex font-bold items-center gap-1"> <span className="flex font-bold items-center gap-1">
<div className="font-light">ثبت شده :</div> <div className="font-light">ثبت شده :</div>
{formatNumber(dashboardData.topData?.registered_innovation_technology_idea || '0')} {formatNumber(
dashboardData.topData
?.registered_innovation_technology_idea || "0",
)}
</span> </span>
<span className="flex items-center gap-1 font-bold"> <span className="flex items-center gap-1 font-bold">
<div className="font-light">در حال اجرا :</div> <div className="font-light">در حال اجرا :</div>
{formatNumber(dashboardData.topData?.ongoing_innovation_technology_ideas || '0')} {formatNumber(
dashboardData.topData
?.ongoing_innovation_technology_ideas || "0",
)}
</span> </span>
</div> </div>
</div> </div>
@ -203,34 +330,43 @@ const chartConfig = {
</div> </div>
</CardContent> </CardContent>
</Card> </Card>
{/* Revenue Card */} {/* Revenue Card */}
<Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm border-gray-700/50"> <Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm border-gray-700/50">
<CardContent className="p-4"> <CardContent className="py-4 px-0">
<div className="flex flex-col justify-between gap-2"> <div className="flex flex-col justify-between gap-2">
<div className="flex justify-between items-center border-b-2 mx-4 border-gray-500/20"> <div className="flex justify-between items-center border-b-2 border-gray-500/20 pb-2">
<h3 className="text-lg font-bold text-white font-persian"> <h3 className="text-lg font-bold text-white font-persian px-6">
افزایش درآمد مبتنی بر فناوری و نوآوری افزایش درآمد مبتنی بر فناوری و نوآوری
</h3> </h3>
</div> </div>
<div className="flex items-center justify-center flex-col p-1"> <div className="flex items-center justify-center flex-col">
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<div className="text-center"> <div className="text-center">
<p className="text-2xl font-bold text-green-400"> <p className="text-5xl font-bold text-green-400">
%{formatNumber(dashboardData.topData?.technology_innovation_based_revenue_growth_percent || '0')} {formatNumber(
</p> dashboardData.topData
<div className="text-xs text-gray-400 font-persian"> ?.technology_innovation_based_revenue_growth || "0",
درصد به کل درآمد )}
</div>
</div>
<div className="text-center">
<p className="text-2xl font-bold text-green-400">
{formatNumber(dashboardData.topData?.technology_innovation_based_revenue_growth || '0')}
</p> </p>
<div className="text-xs text-gray-400 font-persian"> <div className="text-xs text-gray-400 font-persian">
میلیون ریال میلیون ریال
</div> </div>
</div> </div>
<span className="text-6xl font-thin text-gray-600">/</span>
<div className="text-center">
<p className="text-5xl font-bold text-green-400">
{formatNumber(
Math.round(
dashboardData.topData
?.technology_innovation_based_revenue_growth_percent,
) || "0",
)}
%
</p>
<div className="text-xs text-gray-400 font-persian">
درصد به کل درآمد
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -239,31 +375,47 @@ const chartConfig = {
{/* Cost Reduction Card */} {/* Cost Reduction Card */}
<Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm border-gray-700/50"> <Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm border-gray-700/50">
<CardContent className="p-4"> <CardContent className="py-4 px-0">
<div className="flex flex-col justify-between gap-2"> <div className="flex flex-col justify-between gap-2">
<div className="flex justify-between items-center border-b-2 mx-4 border-gray-500/20"> <div className="flex justify-between items-center border-b-2 border-gray-500/20 pb-2">
<h3 className="text-lg font-bold text-white font-persian"> <h3 className="text-lg font-bold text-white font-persian px-6">
کاهش هزینه ها مبتنی بر فناوری و نوآوری کاهش هزینه ها مبتنی بر فناوری و نوآوری
</h3> </h3>
</div> </div>
<div className="flex items-center justify-center flex-col p-1"> <div className="flex items-center justify-center flex-col">
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<div className="text-center"> <div className="text-center">
<p className="text-2xl font-bold text-orange-400"> <p className="text-5xl font-bold text-green-400">
%{formatNumber(dashboardData.topData?.technology_innovation_based_cost_reduction_percent || '0')} {formatNumber(
</p> Math.round(
<div className="text-xs text-gray-400 font-persian"> parseFloat(
درصد به کل هزینه dashboardData.topData?.technology_innovation_based_cost_reduction?.replace(
</div> /,/g,
</div> "",
<div className="text-center"> ) || "0",
<p className="text-2xl font-bold text-orange-400"> ) / 1000000,
{formatNumber(Math.round((parseFloat(dashboardData.topData?.technology_innovation_based_cost_reduction?.replace(/,/g, '') || '0')) / 1000000))} ),
)}
</p> </p>
<div className="text-xs text-gray-400 font-persian"> <div className="text-xs text-gray-400 font-persian">
میلیون ریال میلیون ریال
</div> </div>
</div> </div>
<span className="text-6xl font-thin text-gray-600">/</span>
<div className="text-center">
<p className="text-5xl font-bold text-green-400">
{formatNumber(
Math.round(
dashboardData.topData
?.technology_innovation_based_cost_reduction_percent,
) || "0",
)}
%
</p>
<div className="text-xs text-gray-400 font-persian">
درصد به کل هزینه
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -272,54 +424,116 @@ const chartConfig = {
{/* Budget Ratio Card */} {/* Budget Ratio Card */}
<Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm border-gray-700/50"> <Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm border-gray-700/50">
<CardContent className="p-4"> <CardContent className="py-4 px-0">
<div className="flex flex-col justify-between gap-2"> <div className="flex flex-col justify-between gap-2">
<div className="flex justify-between items-center border-b-2 mx-4 border-gray-500/20"> <div className="flex justify-between items-center border-b-2 border-gray-500/20 pb-2">
<h3 className="text-lg font-bold text-white font-persian"> <h3 className="text-lg font-bold text-white font-persian px-6">
نسبت تحقق بودجه فناوی و نوآوری نسبت تحقق بودجه فناوی و نوآوری
</h3> </h3>
</div> </div>
<div className="flex items-center gap-2 justify-center flex-row-reverse p-1"> <div className="flex items-center gap-2 justify-center flex-row-reverse">
<ChartContainer config={chartConfig} className="w-full h-full max-h-20 max-w-40"> <ChartContainer
<RadialBarChart data={[{ config={chartConfig}
className="w-full h-full max-h-20 max-w-40"
>
<RadialBarChart
data={[
{
browser: "budget", browser: "budget",
visitors: parseFloat(dashboardData.topData?.innovation_budget_achievement_percent || '0'), visitors: parseFloat(
fill: "var(--chart-3)" dashboardData.topData
}]} startAngle={0} endAngle={250} innerRadius={30} outerRadius={50}> ?.innovation_budget_achievement_percent || "0",
),
fill: "green",
},
]}
startAngle={90}
endAngle={
90 +
(dashboardData.topData
?.innovation_budget_achievement_percent /
100) *
360
}
innerRadius={35}
outerRadius={55}
>
<PolarGrid <PolarGrid
gridType="circle" gridType="circle"
radialLines={false} radialLines={false}
stroke="none" stroke="none"
className="first:fill-muted last:fill-background" className="first:fill-red-400 last:fill-background"
polarRadius={[36, 24]} polarRadius={[38, 31]}
/> />
<RadialBar dataKey="visitors" background cornerRadius={5} /> <RadialBar
<PolarRadiusAxis tick={false} tickLine={false} axisLine={false}> dataKey="visitors"
background
cornerRadius={5}
/>
<PolarRadiusAxis
tick={false}
tickLine={false}
axisLine={false}
>
<Label <Label
content={({ viewBox }) => { content={({ viewBox }) => {
if (viewBox && "cx" in viewBox && "cy" in viewBox) { if (viewBox && "cx" in viewBox && "cy" in viewBox) {
return ( return (
<text x={viewBox.cx} y={viewBox.cy} textAnchor="middle" dominantBaseline="middle"> <text
<tspan x={viewBox.cx} y={viewBox.cy} className="fill-foreground text-lg font-bold"> x={viewBox.cx}
%{formatNumber(dashboardData.topData?.innovation_budget_achievement_percent || '0')} y={viewBox.cy}
textAnchor="middle"
dominantBaseline="middle"
>
<tspan
x={viewBox.cx}
y={viewBox.cy}
className="fill-foreground text-lg font-bold"
>
%
{formatNumber(
Math.round(
dashboardData.topData
?.innovation_budget_achievement_percent ||
0,
),
)}
</tspan> </tspan>
</text> </text>
) );
} }
}} }}
/> />
</PolarRadiusAxis> </PolarRadiusAxis>
</RadialBarChart> </RadialBarChart>
</ChartContainer> </ChartContainer>
<div className="font-bold font-persian text-center mt-2"> <div className="font-bold font-persian text-center">
<div className="flex flex-col justify-between items-center"> <div className="flex flex-col justify-between items-center gap-2">
<span className="flex font-bold items-center gap-1"> <span className="flex font-bold items-center gap-1">
<div className="font-light">مصوب :</div> <div className="font-light">مصوب :</div>
{formatNumber(Math.round((parseFloat(dashboardData.topData?.approved_innovation_budget_achievement_ratio?.replace(/,/g, '') || '0')) / 1000000000))} {formatNumber(
Math.round(
parseFloat(
dashboardData.topData?.approved_innovation_budget_achievement_ratio?.replace(
/,/g,
"",
) || "0",
) / 1000000000,
),
)}
</span> </span>
<span className="flex items-center gap-1 font-bold"> <span className="flex items-center gap-1 font-bold">
<div className="font-light">جذب شده :</div> <div className="font-light">جذب شده :</div>
{formatNumber(Math.round((parseFloat(dashboardData.topData?.allocated_innovation_budget_achievement_ratio?.replace(/,/g, '') || '0')) / 1000000000))} {formatNumber(
Math.round(
parseFloat(
dashboardData.topData?.allocated_innovation_budget_achievement_ratio?.replace(
/,/g,
"",
) || "0",
) / 1000000000,
),
)}
</span> </span>
</div> </div>
</div> </div>
@ -330,12 +544,22 @@ const chartConfig = {
</div> </div>
{/* Main Content with Tabs */} {/* Main Content with Tabs */}
<Tabs defaultValue="charts" className=" col-span-2 row-start-2 bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)]"> <Tabs
defaultValue="charts"
className=" col-span-2 row-start-2 bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)]"
>
<TabsList className="bg-transparent"> <TabsList className="bg-transparent">
<TabsTrigger value="charts" className=" text-white data-[state=active]:bg-blue-500/20 data-[state=active]:text-blue-400"> <TabsTrigger
value="charts"
className=" text-white data-[state=active]:bg-blue-500/20 data-[state=active]:text-blue-400"
>
مقایسه ای مقایسه ای
</TabsTrigger> </TabsTrigger>
<TabsTrigger value="canvas" disabled className="text-gray-500 cursor-not-allowed"> <TabsTrigger
value="canvas"
disabled
className="text-gray-500 cursor-not-allowed"
>
شماتیک شماتیک
</TabsTrigger> </TabsTrigger>
</TabsList> </TabsList>
@ -347,21 +571,60 @@ const chartConfig = {
{/* Main Chart */} {/* Main Chart */}
<Card className="bg-transparent px-2 border-none"> <Card className="bg-transparent px-2 border-none">
<CardHeader> <CardHeader>
<CardTitle className="text-white text-xl">تحلیل ارزشها</CardTitle> <CardTitle className="text-white text-xl">
<p className="text-gray-400 text-sm">نمودار مقایسهای عملکرد ماهانه</p> تحلیل ارزشها
</CardTitle>
<p className="text-gray-400 text-sm">
نمودار مقایسهای عملکرد ماهانه
</p>
</CardHeader> </CardHeader>
<CardContent className="border-none"> <CardContent className="border-none">
<div className="h-60 "> <div className="h-60 ">
<ResponsiveContainer width="100%" height="100%"> <ResponsiveContainer width="100%" height="100%">
<LineChart data={[ <LineChart
{ month: 'فروردین', ideas: 12, revenue: 850, cost: 320 }, data={[
{ month: 'اردیبهشت', ideas: 19, revenue: 1200, cost: 450 }, {
{ month: 'خرداد', ideas: 8, revenue: 980, cost: 280 }, month: "فروردین",
{ month: 'تیر', ideas: 15, revenue: 1400, cost: 520 }, ideas: 12,
{ month: 'مرداد', ideas: 22, revenue: 1650, cost: 680 }, revenue: 850,
{ month: 'شهریور', ideas: 18, revenue: 1320, cost: 590 } cost: 320,
]}> },
<CartesianGrid strokeDasharray="3 3" stroke="#374151" /> {
month: "اردیبهشت",
ideas: 19,
revenue: 1200,
cost: 450,
},
{
month: "خرداد",
ideas: 8,
revenue: 980,
cost: 280,
},
{
month: "تیر",
ideas: 15,
revenue: 1400,
cost: 520,
},
{
month: "مرداد",
ideas: 22,
revenue: 1650,
cost: 680,
},
{
month: "شهریور",
ideas: 18,
revenue: 1320,
cost: 590,
},
]}
>
<CartesianGrid
strokeDasharray="3 3"
stroke="#374151"
/>
<XAxis <XAxis
dataKey="month" dataKey="month"
stroke="#9CA3AF" stroke="#9CA3AF"
@ -370,10 +633,10 @@ const chartConfig = {
<YAxis stroke="#9CA3AF" fontSize={11} /> <YAxis stroke="#9CA3AF" fontSize={11} />
<Tooltip <Tooltip
contentStyle={{ contentStyle={{
backgroundColor: '#1F2937', backgroundColor: "#1F2937",
border: '1px solid #374151', border: "1px solid #374151",
borderRadius: '8px', borderRadius: "8px",
color: '#F9FAFB' color: "#F9FAFB",
}} }}
/> />
<Line <Line
@ -382,7 +645,7 @@ const chartConfig = {
stroke="#3B82F6" stroke="#3B82F6"
strokeWidth={3} strokeWidth={3}
name="ایده‌ها" name="ایده‌ها"
dot={{ fill: '#3B82F6', strokeWidth: 2, r: 4 }} dot={{ fill: "#3B82F6", strokeWidth: 2, r: 4 }}
/> />
<Line <Line
type="monotone" type="monotone"
@ -390,7 +653,7 @@ const chartConfig = {
stroke="#10B981" stroke="#10B981"
strokeWidth={3} strokeWidth={3}
name="درآمد (میلیون)" name="درآمد (میلیون)"
dot={{ fill: '#10B981', strokeWidth: 2, r: 4 }} dot={{ fill: "#10B981", strokeWidth: 2, r: 4 }}
/> />
<Line <Line
type="monotone" type="monotone"
@ -398,105 +661,129 @@ const chartConfig = {
stroke="#F59E0B" stroke="#F59E0B"
strokeWidth={3} strokeWidth={3}
name="کاهش هزینه (میلیون)" name="کاهش هزینه (میلیون)"
dot={{ fill: '#F59E0B', strokeWidth: 2, r: 4 }} dot={{ fill: "#F59E0B", strokeWidth: 2, r: 4 }}
/> />
</LineChart> </LineChart>
</ResponsiveContainer> </ResponsiveContainer>
</div> </div>
</CardContent> </CardContent>
</Card> </Card>
</div> </div>
</div> </div>
</TabsContent> </TabsContent>
</Tabs> </Tabs>
{/* Left Section - Status Cards */} {/* Left Section - Status Cards */}
<div className="space-y-4 row-start-2 col-spend-1 "> <div className="space-y-4 row-start-2 col-span-1">
{/* Technology Intensity */} {/* Technology Intensity */}
<Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm border-gray-700/50"> <Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm border-gray-700/50">
<CardContent className="p-4"> <CardContent className="p-4">
<div className="flex items-center gap-3"> <div className="flex items-center justify-center gap-1 px-4">
<CardTitle className="text-white text-base min-w-[120px]">شدت فناوری</CardTitle> <CardTitle className="text-white text-lg min-w-[120px]">
<Progress value={parseFloat(dashboardData.leftData?.technology_intensity || '0')} className="h-2 flex-1" /> شدت فناوری
<p className="text-sm text-gray-400 min-w-[60px] text-left">%{formatNumber(dashboardData.leftData?.technology_intensity || '0')}</p> </CardTitle>
<p className="text-base text-left">
%
{formatNumber(
Math.round(
dashboardData.leftData?.technology_intensity || 0,
),
)}
</p>
<Progress
value={parseFloat(
dashboardData.leftData?.technology_intensity || "0",
)}
className="h-4 flex-1"
/>
</div> </div>
</CardContent> </CardContent>
</Card> </Card>
{/* Program Status */} {/* Program Status */}
<Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm border-gray-700/50"> <Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm border-gray-700/50">
<CardContent className="p-4"> <CardContent className="py-6 px-0">
<CustomBarChart <DashboardCustomBarChart
title="وضعیت برنامه‌های فناوری و نوآوری" title="وضعیت برنامه‌های فناوری و نوآوری"
loading={loading} loading={loading}
data={[ data={[
{ {
label: "اجرا شده", label: "اجرا شده",
value: parseFloat(dashboardData?.leftData?.executed_project || '0'), value: parseFloat(
dashboardData?.leftData?.executed_project || "0",
),
color: "bg-green-400", color: "bg-green-400",
labelColor: "text-white",
}, },
{ {
label: "در حال اجرا", label: "در حال اجرا",
value: parseFloat(dashboardData?.leftData?.in_progress_project || '0'), value: parseFloat(
dashboardData?.leftData?.in_progress_project || "0",
),
color: "bg-blue-400", color: "bg-blue-400",
labelColor: "text-white",
}, },
{ {
label: "برنامه‌ریزی شده", label: "برنامه‌ریزی شده",
value: parseFloat(dashboardData?.leftData?.planned_project || '0'), value: parseFloat(
dashboardData?.leftData?.planned_project || "0",
),
color: "bg-red-400", color: "bg-red-400",
labelColor: "text-white",
}, },
]} ]}
barHeight="h-5"
showAxisLabels={false}
/> />
</CardContent> </CardContent>
</Card> </Card>
{/* Publications */} {/* Publications */}
<Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm border-gray-700/50"> <Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm border-gray-700/50">
<CardHeader className="pb-3"> <CardHeader className="pb-2 border-b-2 border-gray-500/20">
<CardTitle className="text-white text-lg">انتشارات فناوری و نوآوری</CardTitle> <CardTitle className="text-white text-lg">
انتشارات فناوری و نوآوری
</CardTitle>
</CardHeader> </CardHeader>
<CardContent className="p-4"> <CardContent className="p-4">
<div className="grid grid-cols-2 grid-rows-2 gap-3"> <div className="grid grid-cols-2 grid-rows-2 gap-4 justify-center">
<div className="flex items-center justify-between"> <div className="flex items-center justify-center gap-4">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<BookOpen className="w-4 h-4 text-blue-400" /> <BookOpen className="w-4 h-4 text-blue-400" />
<span className="text-gray-300 text-sm">کتاب:</span> <span className="text-base">کتاب:</span>
</div> </div>
<span className="text-lg font-bold text-blue-400"> <span className="text-xl font-bold ">
{formatNumber(dashboardData.leftData?.printed_books_count || '0')} {formatNumber(
dashboardData.leftData?.printed_books_count || "0",
)}
</span> </span>
</div> </div>
<div className="flex items-center justify-between"> <div className="flex items-center justify-center gap-4">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<BookOpen className="w-4 h-4 text-purple-400" /> <BookOpen className="w-4 h-4 text-purple-400" />
<span className="text-gray-300 text-sm">پتنت:</span> <span className="text-base">پتنت:</span>
</div> </div>
<span className="text-lg font-bold text-purple-400"> <span className="text-xl font-bold ">
{formatNumber(dashboardData.leftData?.registered_patents_count || '0')} {formatNumber(
dashboardData.leftData?.registered_patents_count || "0",
)}
</span> </span>
</div> </div>
<div className="flex items-center justify-between"> <div className="flex items-center justify-center gap-4">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<BookOpen className="w-4 h-4 text-yellow-400" /> <BookOpen className="w-4 h-4 text-yellow-400" />
<span className="text-gray-300 text-sm">گزارش:</span> <span className="text-base">گزارش:</span>
</div> </div>
<span className="text-lg font-bold text-yellow-400"> <span className="text-xl font-bold ">
{formatNumber(dashboardData.leftData?.published_reports_count || '0')} {formatNumber(
dashboardData.leftData?.published_reports_count || "0",
)}
</span> </span>
</div> </div>
<div className="flex items-center justify-between"> <div className="flex items-center justify-center gap-4">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<BookOpen className="w-4 h-4 text-green-400" /> <BookOpen className="w-4 h-4 text-green-400" />
<span className="text-gray-300 text-sm">مقاله:</span> <span className="text-base">مقاله:</span>
</div> </div>
<span className="text-lg font-bold text-green-400"> <span className="text-xl font-bold ">
{formatNumber(dashboardData.leftData?.printed_articles_count || '0')} {formatNumber(
dashboardData.leftData?.printed_articles_count || "0",
)}
</span> </span>
</div> </div>
</div> </div>
@ -505,53 +792,61 @@ const chartConfig = {
{/* Promotion */} {/* Promotion */}
<Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm border-gray-700/50"> <Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm border-gray-700/50">
<CardHeader className="pb-3"> <CardHeader className="pb-2 border-b-2 border-gray-500/20">
<CardTitle className="text-white text-lg">ترویج فناوری و نوآوری</CardTitle> <CardTitle className="text-white text-lg">
ترویج فناوری و نوآوری
</CardTitle>
</CardHeader> </CardHeader>
<CardContent className="p-4"> <CardContent className="p-4">
<div className="space-y-3"> <div className="grid grid-cols-2 grid-rows-2 gap-4 justify-center">
<div className="flex items-center justify-between"> <div className="flex items-center justify-center gap-4">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<BookOpen className="w-4 h-4 text-purple-400" /> <BookOpen className="w-4 h-4 text-purple-400" />
<span className="text-gray-300 text-sm">کنفرانس:</span> <span className="text-base">کنفرانس:</span>
</div> </div>
<span className="text-lg font-bold text-purple-400"> <span className="text-xl font-bold ">
{formatNumber(dashboardData.leftData?.attended_conferences_count || '0')} {formatNumber(
dashboardData.leftData?.attended_conferences_count || "0",
)}
</span> </span>
</div> </div>
<div className="flex items-center justify-between"> <div className="flex items-center justify-center gap-4">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<BookOpen className="w-4 h-4 text-blue-400" /> <BookOpen className="w-4 h-4 text-blue-400" />
<span className="text-gray-300 text-sm">شرکت در رویداد:</span> <span className="text-base">شرکت در رویداد:</span>
</div> </div>
<span className="text-lg font-bold text-blue-400"> <span className="text-xl font-bold ">
{formatNumber(dashboardData.leftData?.attended_events_count || '0')} {formatNumber(
dashboardData.leftData?.attended_events_count || "0",
)}
</span> </span>
</div> </div>
<div className="flex items-center justify-between"> <div className="flex items-center justify-center gap-4">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<BookOpen className="w-4 h-4 text-yellow-400" /> <BookOpen className="w-4 h-4 text-yellow-400" />
<span className="text-gray-300 text-sm">نمایشگاه:</span> <span className="text-base">نمایشگاه:</span>
</div> </div>
<span className="text-lg font-bold text-yellow-400"> <span className="text-xl font-bold ">
{formatNumber(dashboardData.leftData?.attended_exhibitions_count || '0')} {formatNumber(
dashboardData.leftData?.attended_exhibitions_count || "0",
)}
</span> </span>
</div> </div>
<div className="flex items-center justify-between"> <div className="flex items-center justify-center gap-4">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<BookOpen className="w-4 h-4 text-green-400" /> <BookOpen className="w-4 h-4 text-green-400" />
<span className="text-gray-300 text-sm">برگزاری رویداد:</span> <span className="text-base">برگزاری رویداد:</span>
</div> </div>
<span className="text-lg font-bold text-green-400"> <span className="text-xl font-bold ">
{formatNumber(dashboardData.leftData?.organized_events_count || '0')} {formatNumber(
dashboardData.leftData?.organized_events_count || "0",
)}
</span> </span>
</div> </div>
</div> </div>
</CardContent> </CardContent>
</Card> </Card>
</div> </div>
</div> </div>
</DashboardLayout> </DashboardLayout>
); );