feat/green-innovation #6
|
|
@ -21,19 +21,34 @@ import {
|
|||
DialogTitle,
|
||||
} from "~/components/ui/dialog";
|
||||
import {
|
||||
ChevronUp,
|
||||
ChevronDown,
|
||||
RefreshCw,
|
||||
ExternalLink,
|
||||
Building2,
|
||||
PickaxeIcon,
|
||||
UserIcon,
|
||||
UsersIcon,
|
||||
} from "lucide-react";
|
||||
BarChart,
|
||||
Bar,
|
||||
XAxis,
|
||||
YAxis,
|
||||
CartesianGrid,
|
||||
Tooltip,
|
||||
ResponsiveContainer,
|
||||
LineChart,
|
||||
Line,
|
||||
Rectangle,
|
||||
Legend,
|
||||
} from "recharts";
|
||||
|
||||
import apiService from "~/lib/api";
|
||||
import toast from "react-hot-toast";
|
||||
import { Funnel, Wrench, CirclePause, DollarSign } from "lucide-react";
|
||||
import ProjectDetail from "../projects/project-detail";
|
||||
import {
|
||||
LoaderCircle,
|
||||
TrendingUp,
|
||||
Key,
|
||||
Sparkle,
|
||||
Zap,
|
||||
Flame,
|
||||
Building2,
|
||||
PickaxeIcon,
|
||||
UsersIcon,
|
||||
UserIcon,
|
||||
RefreshCw,
|
||||
} from "lucide-react";
|
||||
import DashboardLayout from "../layout";
|
||||
|
||||
moment.loadPersian({ usePersianDigits: true });
|
||||
|
|
@ -80,6 +95,19 @@ interface InnovationStats {
|
|||
percentFailuresReduction: number; // درصد مقایسهای کاهش خرابیهای پرتکرار
|
||||
}
|
||||
|
||||
interface Params {
|
||||
icon: any;
|
||||
label: string;
|
||||
value: string;
|
||||
suffix: string;
|
||||
}
|
||||
interface RecycleParams {
|
||||
water: Params;
|
||||
food: Params;
|
||||
power: Params;
|
||||
oil: Params;
|
||||
}
|
||||
|
||||
const columns = [
|
||||
{ key: "select", label: "", sortable: false, width: "50px" },
|
||||
{ key: "project_no", label: "شماره پروژه", sortable: true, width: "140px" },
|
||||
|
|
@ -131,6 +159,32 @@ export function GreenInnovationPage() {
|
|||
const [detailsDialogOpen, setDetailsDialogOpen] = useState(false);
|
||||
const [selectedProjectDetails, setSelectedProjectDetails] =
|
||||
useState<ProcessInnovationData | null>(null);
|
||||
const [recycleParams, setRecycleParams] = useState<RecycleParams>({
|
||||
water: {
|
||||
icon: <Key className="text-emerald-400" size={"18px"} />,
|
||||
label: "آب",
|
||||
value: "1,520",
|
||||
suffix: "لیتر",
|
||||
},
|
||||
food: {
|
||||
icon: <Sparkle className="text-emerald-400" size={"18px"} />,
|
||||
label: "خوراک",
|
||||
value: "520",
|
||||
suffix: "تن",
|
||||
},
|
||||
oil: {
|
||||
icon: <Flame className="text-emerald-400" size={"18px"} />,
|
||||
label: "سوخت",
|
||||
value: "250",
|
||||
suffix: "متر مربع",
|
||||
},
|
||||
power: {
|
||||
icon: <Zap className="text-emerald-400" size={"18px"} />,
|
||||
label: "برق",
|
||||
value: "650",
|
||||
suffix: "میلیون مگاوات",
|
||||
},
|
||||
});
|
||||
const observerRef = useRef<HTMLDivElement>(null);
|
||||
const fetchingRef = useRef(false);
|
||||
|
||||
|
|
@ -579,14 +633,20 @@ export function GreenInnovationPage() {
|
|||
}
|
||||
};
|
||||
|
||||
const data = [
|
||||
{ name: recycleParams.water.label, pv: 70, amt: 80 },
|
||||
{ name: recycleParams.power.label, pv: 45, amt: 60 },
|
||||
{ name: recycleParams.oil.label, pv: 90, amt: 75 },
|
||||
{ name: recycleParams.food.label, pv: 30, amt: 50 },
|
||||
];
|
||||
|
||||
return (
|
||||
<DashboardLayout title="نوآوری سبز">
|
||||
<div className="p-6 space-y-4">
|
||||
{/* Stats Cards */}
|
||||
<div className="flex gap-6">
|
||||
<div className="space-y-6 w-full">
|
||||
<div className="flex gap-6 mb-6">
|
||||
<div className="flex flex-col gap-11 w-full h-full">
|
||||
{/* Stats Grid */}
|
||||
<div className="flex flex-col gap-3">
|
||||
{loading || statsLoading
|
||||
? // Loading skeleton for stats cards - matching new design
|
||||
Array.from({ length: 2 }).map((_, index) => (
|
||||
|
|
@ -595,7 +655,7 @@ export function GreenInnovationPage() {
|
|||
className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm rounded-2xl overflow-hidden"
|
||||
>
|
||||
<CardContent className="p-2">
|
||||
<div className="flex flex-col justify-between gap-2">
|
||||
<div className="flex flex-col justify-between gap-2 h-full">
|
||||
<div className="flex justify-between items-center border-b-2 border-gray-500/20">
|
||||
<div
|
||||
className="h-6 bg-gray-600 rounded animate-pulse"
|
||||
|
|
@ -624,64 +684,153 @@ export function GreenInnovationPage() {
|
|||
key={card.id}
|
||||
className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm border-gray-700/50"
|
||||
>
|
||||
<CardContent className="p-0">
|
||||
<div className="flex flex-col justify-between gap-2">
|
||||
<CardContent className="p-0 h-full">
|
||||
<div className="flex flex-col justify-between gap-2 h-full">
|
||||
<div className="flex justify-between items-center border-b-2 border-gray-500/20 ">
|
||||
<h3 className="text-lg font-bold text-white font-persian p-4">
|
||||
{card.title}
|
||||
</h3>
|
||||
</div>
|
||||
<div className="flex items-center justify-between p-6">
|
||||
<span className="text-emerald-400">
|
||||
<div className="flex items-center justify-between p-6 flex-row-reverse">
|
||||
<div className="flex flex-col">
|
||||
<span className="text-3xl font-bold text-emerald-400 mb-1">
|
||||
% {card.percent.value}
|
||||
</span>
|
||||
<span className="text-sm text-gray-400 font-persian">
|
||||
{card.percent.description}
|
||||
</span>
|
||||
</div>
|
||||
<b className="block w-0.5 h-12 bg-gray-600 rotate-45" />
|
||||
<div className="flex flex-col">
|
||||
<span className="text-3xl font-bold text-emerald-400 mb-1">
|
||||
{card.total.value}
|
||||
</span>
|
||||
<b className="block w-0.5 h-8 bg-emerald-400 rotate-45" />
|
||||
<span className="text-emerald-400">
|
||||
{card.percent.value}
|
||||
<span className="text-sm text-gray-400 font-persian">
|
||||
{card.total.description}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Process Impacts Chart */}
|
||||
<Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm rounded-2xl w-full overflow-hidden">
|
||||
<CardContent className="p-4">
|
||||
<CustomBarChart
|
||||
title="تاثیرات فرآیندی به صورت درصد مقایسه ای"
|
||||
loading={statsLoading}
|
||||
data={[
|
||||
{
|
||||
label: "کاهش توقفات تولید",
|
||||
value: stats.percentProductionStops || 0,
|
||||
color: "bg-emerald-400",
|
||||
labelColor: "text-white",
|
||||
},
|
||||
{
|
||||
label: "رفع گلوگاه تولید",
|
||||
value: stats.percentBottleneckRemoval || 0,
|
||||
color: "bg-emerald-400",
|
||||
labelColor: "text-white",
|
||||
},
|
||||
{
|
||||
label: "کاهش ارز بری",
|
||||
value: stats.percentCurrencyReduction || 0,
|
||||
color: "bg-emerald-400",
|
||||
labelColor: "text-white",
|
||||
},
|
||||
{
|
||||
label: "کاهش خرابی پر تکرار",
|
||||
value: stats.percentFailuresReduction || 0,
|
||||
color: "bg-emerald-400",
|
||||
labelColor: "text-white",
|
||||
},
|
||||
]}
|
||||
barHeight="h-5"
|
||||
showAxisLabels={true}
|
||||
<CardContent className="p-0 h-full overflow-hidden">
|
||||
<div className="border-b-2 border-gray-500/20">
|
||||
<div className="w-full p-4 px-6">
|
||||
<span>بازیافت و بازیابی منابع</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="content grid gap-3 h-max p-8 box-border items-center justify-between sm:grid-cols-1 sm:overflow-auto xl:overflow-hidden xl:grid-cols-[30%_70%]">
|
||||
<div className="params flex flex-col gap-3.5">
|
||||
{Object.entries(recycleParams).map((el, index) => {
|
||||
return (
|
||||
<div className="param flex flex-row justify-between items-center">
|
||||
<div className="flex flex-row gap-2">
|
||||
{el[1].icon}
|
||||
<span className="font-normal text-sm">
|
||||
{el[1].label}:
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex flex-row gap-1.5 items-center">
|
||||
<span className="text-sm font-normal">
|
||||
{el[1].value}
|
||||
</span>
|
||||
<span className="text-sm">{el[1].suffix}</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="h-72 w-[32rem]">
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<BarChart
|
||||
width={500}
|
||||
height={300}
|
||||
data={data}
|
||||
margin={{
|
||||
top: 5,
|
||||
right: 30,
|
||||
left: 20,
|
||||
bottom: 5,
|
||||
}}
|
||||
>
|
||||
<CartesianGrid
|
||||
stroke="#374151"
|
||||
strokeDasharray="0"
|
||||
vertical={false} // خطهای عمودی (از محور X) بمونه
|
||||
// horizontal={false} // خطهای افقی (از محور Y) حذف میشه
|
||||
/>
|
||||
<XAxis
|
||||
dataKey="name"
|
||||
axisLine={false} // خط اصلی محور X محو میشه
|
||||
tickLine={false}
|
||||
tick={{
|
||||
fill: "#fff",
|
||||
fontSize: 14,
|
||||
fontWeight: "normal",
|
||||
dy: 10, // جابجایی عمودی (مثبت = پایینتر، منفی = بالاتر)
|
||||
}}
|
||||
/>
|
||||
<YAxis
|
||||
type="number"
|
||||
domain={[0, 100]}
|
||||
axisLine={false}
|
||||
tickLine={false}
|
||||
tick={{
|
||||
fill: "#99a1af", // رنگ متن
|
||||
fontSize: 14, // سایز فونت
|
||||
// fontWeight: "bold", // ضخامت
|
||||
dx: -30, // جابجایی افقی (اعداد نزدیکتر یا دورتر از محور)
|
||||
// dy:-1
|
||||
}}
|
||||
tickFormatter={(val) => `${val}%`}
|
||||
/>
|
||||
<Bar
|
||||
dataKey="pv"
|
||||
fill="#3AEA83"
|
||||
radius={[20, 20, 0, 0]}
|
||||
barSize={14}
|
||||
label={{
|
||||
position: "top",
|
||||
fill: "#fff",
|
||||
fontWeight: "bold",
|
||||
}}
|
||||
/>
|
||||
</BarChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm rounded-2xl w-full overflow-hidden">
|
||||
<CardContent className="p-0">
|
||||
<div className="border-b-2 border-gray-500/20">
|
||||
<div className="flex flex-row justify-between w-full p-4 px-6">
|
||||
<span>استاندارد ها و مقررات</span>
|
||||
<TrendingUp />
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col gap-3 p-4 max-h-[22rem] overflow-y-scroll">
|
||||
{Array.from({ length: 10 }, (index) => {
|
||||
return (
|
||||
<div key={`${index}-1`} className="flex gap-2">
|
||||
<LoaderCircle
|
||||
size={"18px"}
|
||||
className="text-emerald-400"
|
||||
/>
|
||||
<span>استاندارد Iso 2005</span>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user