fix styles in cards
This commit is contained in:
parent
96f283b951
commit
4248237df0
74
app/components/dashboard/dashboard-custom-bar-chart.tsx
Normal file
74
app/components/dashboard/dashboard-custom-bar-chart.tsx
Normal 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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -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,13 +101,21 @@ 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();
|
||||||
|
|
@ -98,11 +130,10 @@ const chartConfig = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
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>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user