fix: green inivation designed bugs

This commit is contained in:
MehrdadAdabi 2025-08-30 18:21:46 +03:30
parent 69cea7a06c
commit 28f22dd0d3
2 changed files with 147 additions and 110 deletions

View File

@ -69,6 +69,7 @@ interface DigitalInnovationMetrics {
reduce_energy_consumption_percent: string;
resource_productivity: string;
resource_productivity_percent: string;
average_project_score?: number;
}
// Normalized interface for digital innovation stats
@ -82,6 +83,8 @@ interface DigitalInnovationStats {
reduceEnergyConsumptionPercent: number;
resourceProductivity: number;
resourceProductivityPercent: number;
avarageProjectScore: number;
countInnovationDigitalProjects: number;
}
enum DigitalCardLabel {
@ -168,6 +171,7 @@ export function DigitalInnovationPage() {
reduceEnergyConsumptionPercent: 0,
resourceProductivity: 0,
resourceProductivityPercent: 0,
avarageProjectScore: 0,
});
const [sortConfig, setSortConfig] = useState<SortConfig>({
field: "start_date",
@ -177,7 +181,7 @@ export function DigitalInnovationPage() {
new Set()
);
const [detailsDialogOpen, setDetailsDialogOpen] = useState(false);
const [avarage, setAvarage] = useState<number>(0);
// const [avarage, setAvarage] = useState<number>(0);
const observerRef = useRef<HTMLDivElement>(null);
const fetchingRef = useRef(false);
@ -288,7 +292,6 @@ export function DigitalInnovationPage() {
Pagination: { PageNumber: pageToFetch, PageSize: pageSize },
});
// console.log(JSON.parse(response.data));
if (response.state === 0) {
const dataString = response.data;
if (dataString && typeof dataString === "string") {
@ -297,7 +300,7 @@ export function DigitalInnovationPage() {
if (Array.isArray(parsedData)) {
if (reset) {
setProjects(parsedData);
calculateAverage(parsedData);
// calculateAverage(parsedData);
setTotalCount(parsedData.length);
} else {
setProjects((prev) => [...prev, ...parsedData]);
@ -422,8 +425,6 @@ export function DigitalInnovationPage() {
const parsedData = JSON.parse(dataString);
if (Array.isArray(parsedData) && parsedData[0]) {
const count = parsedData[0].project_no_count || 0;
setActualTotalCount(count);
// Keep stats in sync if backend stats not yet loaded
setStats((prev) => ({ ...prev, totalProjects: count }));
}
} catch (parseError) {
@ -440,7 +441,7 @@ export function DigitalInnovationPage() {
const fetchStats = async () => {
try {
setStatsLoading(true);
const raw = await apiService.callInnovationProcess<any>({
const raw = await apiService.call<any>({
innovation_digital_function: {},
});
@ -474,8 +475,10 @@ export function DigitalInnovationPage() {
resourceProductivityPercent: parseNum(
payload?.resource_productivity_percent
),
avarageProjectScore: parseNum(payload?.average_project_score),
countInnovationDigitalProjects: parseNum(payload?.count_innovation_digital_projects),
};
setActualTotalCount(normalized.countInnovationDigitalProjects);
setStats(normalized);
} catch (error) {
console.error("Error fetching stats:", error);
@ -532,7 +535,7 @@ export function DigitalInnovationPage() {
}
}, [rating]);
const ststusColor = (status: projectStatus): any => {
const statusColor = (status: projectStatus): any => {
let el = null;
switch (status) {
case projectStatus.contract:
@ -597,7 +600,7 @@ export function DigitalInnovationPage() {
return (
<div className="flex items-center gap-1">
<Badge
variant={ststusColor(value)}
variant={statusColor(value)}
className="font-medium border-2 p-0 block w-2 h-2 rounded-full"
style={{
border: "none",
@ -625,22 +628,22 @@ export function DigitalInnovationPage() {
}
};
const calculateAverage = (data: Array<ProcessInnovationData>) => {
let number = 0;
data.map(
(item: ProcessInnovationData) => (number = number + +item.project_rating)
);
setAvarage(number / data.length);
};
// const calculateAverage = (data: Array<ProcessInnovationData>) => {
// let number = 0;
// data.map(
// (item: ProcessInnovationData) => (number = number + +item.project_rating)
// );
// setAvarage(number / data.length);
// };
return (
<DashboardLayout title="نوآوری دیجیتال">
<div className="flex flex-row gap-8 justify-between p-6 space-y-4 h-full">
<div className="grid grid-cols-2 gap-8 justify-between p-6 space-y-4 h-full">
{/* Stats Cards */}
<div className="flex flex-col gap-4 w-full">
<div className="flex flex-col justify-between gap-5 w-full mb-0 h-[calc(90vh-12rem)]">
<div className="space-y-6 w-full">
{/* Stats Grid */}
<div className="grid grid-cols-2 gap-3">
<div className="grid grid-cols-2 gap-5">
{loading || statsLoading
? // Loading skeleton for stats cards - matching new design
Array.from({ length: 4 }).map((_, index) => (
@ -648,18 +651,18 @@ export function DigitalInnovationPage() {
key={`skeleton-${index}`}
className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm rounded-2xl overflow-hidden"
>
<CardContent className="p-2">
<CardContent className="p-0">
<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 px-6 py-4 border-gray-500/20">
<div
className="h-6 bg-gray-600 rounded animate-pulse"
style={{ width: "60%" }}
/>
<div className="p-3 bg-emerald-500/20 rounded-full w-fit">
<div className="bg-emerald-500/20 rounded-full w-fit">
<div className="w-6 h-6 bg-gray-600 rounded animate-pulse" />
</div>
</div>
<div className="flex items-center justify-center flex-col p-1">
<div className="flex items-center justify-center flex-col p-4">
<div
className="h-8 bg-gray-600 rounded mb-1 animate-pulse"
style={{ width: "40%" }}
@ -678,19 +681,19 @@ export function DigitalInnovationPage() {
key={card.id}
className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm border-gray-700/50"
>
<CardContent className="p-2">
<CardContent className="p-0">
<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">
<h3 className="text-lg font-bold text-white font-persian">
<div className="flex justify-between items-center border-b-2 px-6 border-gray-500/20">
<h3 className="text-lg font-bold text-white font-persian py-4">
{card.title}
</h3>
<div
className={`p-3 gird placeitems-center rounded-full w-fit `}
className={`gird placeitems-center rounded-full w-fit`}
>
{card.icon}
</div>
</div>
<div className="flex items-center justify-center flex-col p-1">
<div className="flex items-center justify-center flex-col p-2 pb-4">
<p
className={`text-3xl font-bold ${card.color} mb-1`}
>
@ -708,7 +711,7 @@ export function DigitalInnovationPage() {
</div>
{/* Process Impacts Chart */}
<Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm rounded-2xl w-full overflow-hidden">
<Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm rounded-lg w-full overflow-hidden">
{/* <CardContent > */}
<CustomBarChart
title="تاثیرات نوآوری دیجیتال به صورت درصد مقایسه ای"
@ -747,10 +750,10 @@ export function DigitalInnovationPage() {
</div>
{/* Data Table */}
<Card className="bg-transparent backdrop-blur-sm rounded-2xl overflow-hidden w-full h-max">
<Card className="bg-transparent backdrop-blur-sm rounded-lg overflow-hidden w-full h-max">
<CardContent className="p-0">
<div className="relative">
<Table containerClassName="overflow-auto custom-scrollbar h-[calc(90vh-270px)]">
<div className="relative h-full">
<Table containerClassName="overflow-auto custom-scrollbar w-full h-[calc(90vh-15rem)]">
<TableHeader>
<TableRow className="bg-[#3F415A]">
{columns.map((column) => (
@ -864,30 +867,29 @@ export function DigitalInnovationPage() {
{/* Footer */}
<div className="p-2 px-4 bg-gray-700/50">
<div className="grid grid-cols-6 gap-4 text-sm text-gray-300 font-persian">
<div className="text-center gap-2 items-center flex">
<div className="flex flex-row gap-4 text-sm text-gray-300 font-persian justify-between">
<div className="text-center gap-2 items-center w-1/3 pr-16">
<div className="text-base text-gray-401 mb-1">
کل پروژه ها :{formatNumber(actualTotalCount)}
کل پروژه ها : {formatNumber(actualTotalCount)}
</div>
</div>
{/* Project number column - empty */}
<div></div>
{/* Title column - empty */}
<div></div>
{/* Project status column - empty */}
<div className="flex items-center flex-row-reverse status ">
<span className="block w-7 h-2.5 bg-violet-500 rounded-tl-xl rounded-bl-xl"></span>
<span className="block w-7 h-2.5 bg-purple-500 "></span>
<span className="block w-7 h-2.5 bg-cyan-300 "></span>
<span className="block w-7 h-2.5 bg-pink-400 rounded-tr-xl rounded-br-xl"></span>
</div>
{/* Project rating column - show average */}
<div className="flex justify-center items-center gap-2">
<div className="text-base text-gray-400 mb-1">
میانگین امتیاز :
<div className="flex items-center flex-row gap-4 status w-1/2 justify-center">
<div className="flex flex-row-reverse">
<span className="block w-7 h-2.5 bg-violet-500 rounded-tl-xl rounded-bl-xl"></span>
<span className="block w-7 h-2.5 bg-purple-500 "></span>
<span className="block w-7 h-2.5 bg-cyan-300 "></span>
<span className="block w-7 h-2.5 bg-pink-400 rounded-tr-xl rounded-br-xl"></span>
</div>
<div className="font-bold">
{formatNumber(((avarage ?? 0) as number).toFixed?.(1) ?? 0)}
<div className="flex justify-center items-center gap-2">
<div className="text-base text-gray-400 mb-1">میانگین :</div>
<div className="font-bold">
{formatNumber(
((stats.avarageProjectScore ?? 0) as number).toFixed?.(
1
) ?? 0
)}
</div>
</div>
</div>
</div>

View File

@ -99,27 +99,10 @@ interface InnovationStats {
waste_reduction_percent: number;
water_recovery_reduction: number;
water_recovery_reduction_percent: number;
average_project_score:number
average_project_score: number;
count_innovation_green_projects: number;
}
interface GreenInnovationState {
water: {
value: any;
percent: number;
};
food: {
value: any;
percent: number;
};
power: {
value: any;
percent: number;
};
oil: {
value: any;
percent: number;
};
}
interface Params {
icon: any;
@ -145,6 +128,16 @@ interface ChartDataItem {
amt: number; // max value or target
}
enum projectStatus {
propozal = "پروپوزال",
contract = "پیشنویس قرارداد",
inprogress = "در حال انجام",
stop = "متوقف شده",
mafasa = "مرحله مفاصا",
finish = "پایان یافته",
}
const columns = [
{ key: "select", label: "", sortable: false, width: "50px" },
{ key: "project_no", label: "شماره پروژه", sortable: true, width: "140px" },
@ -179,7 +172,7 @@ export function GreenInnovationPage() {
field: "start_date",
direction: "asc",
});
const [tblAvarage , setTblAvarage] = useState<number>(0);
const [tblAvarage, setTblAvarage] = useState<number>(0);
const [selectedProjects, setSelectedProjects] = useState<Set<string>>(
new Set()
);
@ -215,7 +208,7 @@ export function GreenInnovationPage() {
value: 0,
suffix: "متر مربع",
percent: 0,
}
},
});
const [sustainabilityStats, setSustainabilityStats] = useState<StatsCard>({
pollution: {
@ -431,7 +424,6 @@ export function GreenInnovationPage() {
const parsedData = JSON.parse(dataString);
if (Array.isArray(parsedData) && parsedData[0]) {
const count = parsedData[0].project_no_count || 0;
setActualTotalCount(count);
// Keep stats in sync if backend stats not yet loaded
setStats((prev) => ({ ...prev, totalProjects: count }));
}
@ -510,9 +502,11 @@ export function GreenInnovationPage() {
percent: formatNumber(parseNum(stats.waste_reduction_percent)),
},
avarage: stats.average_project_score
avarage: stats.average_project_score,
countInnovationGreenProjects: stats.count_innovation_green_projects,
};
setTblAvarage(normalized.avarage)
setActualTotalCount(normalized.countInnovationGreenProjects);
setTblAvarage(normalized.avarage);
setPageData(normalized);
} catch (error) {
console.error("Error fetching stats:", error);
@ -623,18 +617,19 @@ export function GreenInnovationPage() {
);
case "title":
return <span className="font-medium text-white">{String(value)}</span>;
case "project_status":
return (
<Badge
variant="outline"
className="font-medium border-2"
style={{
border: "none",
}}
>
{String(value)}
</Badge>
);
case "project_status":
return (
<div className="flex items-center gap-1">
<Badge
variant={statusColor(value)}
className="font-medium border-2 p-0 block w-2 h-2 rounded-full"
style={{
border: "none",
}}
></Badge>
{String(value)}
</div>
);
case "project_rating":
return (
<Badge variant="outline" className="text-lg text-center border-none">
@ -654,6 +649,30 @@ export function GreenInnovationPage() {
}
};
const statusColor = (status: projectStatus): any => {
let el = null;
switch (status) {
case projectStatus.contract:
el = "teal";
break;
case projectStatus.finish:
el = "info";
break;
case projectStatus.stop:
el = "warning";
break;
case projectStatus.inprogress:
el = "teal";
break;
case projectStatus.mafasa:
el = "destructive";
break;
case projectStatus.propozal:
el = "info";
}
return el;
};
const [chartData, setChartData] = useState<Array<ChartDataItem>>([
{ name: recycleParams.water.label, pv: 70, amt: 80 },
{ name: recycleParams.power.label, pv: 45, amt: 60 },
@ -673,7 +692,7 @@ export function GreenInnovationPage() {
Array.from({ length: 2 }).map((_, index) => (
<Card
key={`skeleton-${index}`}
className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm rounded-2xl overflow-hidden"
className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm rounded-lg overflow-hidden"
>
<CardContent className="p-0 h-48">
<div className="flex flex-col gap-2 h-full">
@ -700,7 +719,7 @@ export function GreenInnovationPage() {
: Object.entries(sustainabilityStats).map(([key, value]) => (
<Card
key={key}
className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] rounded-2xl backdrop-blur-sm border-gray-700/50"
className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] rounded-lg backdrop-blur-sm border-gray-700/50"
>
<CardContent className="p-0 h-full">
<div className="flex flex-col justify-between gap-2 h-full">
@ -737,7 +756,7 @@ export function GreenInnovationPage() {
{/* Process Impacts Chart */}
{statsLoading ? (
<Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm rounded-2xl w-full overflow-hidden">
<Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] h-[calc(90vh-24.3rem)] backdrop-blur-sm rounded-lg w-full overflow-hidden">
<CardContent className="p-0 h-full">
<div className="border-b-2 border-gray-500/20">
<div className="w-full p-4 px-6">
@ -745,7 +764,7 @@ export function GreenInnovationPage() {
</div>
</div>
<div className="content grid gap-6 h-max p-8 box-border items-center justify-between sm:grid-cols-1 xl:grid-cols-[30%_70%]">
<div className="content grid gap-6 h-full p-8 box-border items-center justify-between sm:grid-cols-1 xl:grid-cols-[30%_70%]">
<div className="params flex flex-col gap-3.5">
{[...Array(3)].map((_, paramIndex) => (
<div
@ -780,7 +799,7 @@ export function GreenInnovationPage() {
</CardContent>
</Card>
) : (
<Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm rounded-2xl w-full overflow-hidden">
<Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] h-[calc(90vh-26rem)] backdrop-blur-sm rounded-lg w-full overflow-hidden">
<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">
@ -861,7 +880,7 @@ export function GreenInnovationPage() {
position: "top",
fill: "#fff",
fontWeight: "bold",
formatter: (value:any) => `${value}%`,
formatter: (value: any) => `${value}%`,
}}
/>
</BarChart>
@ -872,7 +891,7 @@ export function GreenInnovationPage() {
</Card>
)}
<Card className="w-1/3 bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm rounded-2xl overflow-hidden">
<Card className="w-1/3 bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm rounded-lg 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">
@ -890,9 +909,7 @@ export function GreenInnovationPage() {
</div>
</div>
<div
className={'flex flex-col gap-3 p-4overflow-y-hidden p-4'}
>
<div className={"flex flex-col gap-3 p-4overflow-y-hidden p-4"}>
{statsLoading
? Array.from({ length: 10 }).map((_, index) => (
<div key={index} className="flex gap-2 items-center">
@ -915,7 +932,7 @@ export function GreenInnovationPage() {
</div>
{/* Data Table */}
<Card className="bg-transparent backdrop-blur-sm rounded-2xl overflow-hidden">
<Card className="bg-transparent backdrop-blur-sm rounded-lg overflow-hidden">
<CardContent className="p-0">
<div className="relative">
<Table containerClassName="overflow-auto custom-scrollbar max-h-[calc(90vh-400px)]">
@ -1019,8 +1036,34 @@ export function GreenInnovationPage() {
</div>
</CardContent>
{/* Footer */}
<div className="p-2 px-4 bg-gray-700/50">
<div className="flex flex-row gap-4 text-sm text-gray-300 font-persian justify-between">
<div className="text-center gap-2 items-center w-1/3 pr-36">
<div className="text-base text-gray-401 mb-1">
کل پروژه ها :{formatNumber(actualTotalCount)}
</div>
</div>
<div className="flex items-center flex-row gap-20 status justify-center w-2/3">
<div className="flex flex-row-reverse">
<span className="block w-7 h-2.5 bg-violet-500 rounded-tl-xl rounded-bl-xl"></span>
<span className="block w-7 h-2.5 bg-purple-500 "></span>
<span className="block w-7 h-2.5 bg-cyan-300 "></span>
<span className="block w-7 h-2.5 bg-pink-400 rounded-tr-xl rounded-br-xl"></span>
</div>
<div className="flex justify-center items-center gap-2">
<div className="text-base text-gray-400 mb-1">میانگین :</div>
<div className="font-bold">
{formatNumber(
((tblAvarage ?? 0) as number).toFixed?.(1) ?? 0
)}
</div>
</div>
</div>
</div>
</div>
{/* <div className="p-2 px-4 bg-gray-700/50">
<div className="grid grid-cols-6 gap-4 text-sm text-gray-300 font-persian">
<div className="text-center gap-2 items-center flex">
<div className="text-base text-gray-401 mb-1">
@ -1029,13 +1072,7 @@ export function GreenInnovationPage() {
{formatNumber(stats?.totalProjects || actualTotalCount)}
</div>
</div>
{/* Project number column - empty */}
<div></div>
{/* Title column - empty */}
<div></div>
{/* Project status column - empty */}
<div></div>
{/* Project rating column - show average */}
<div className="flex justify-center items-center gap-2">
<div className="text-base text-gray-400 mb-1">
{" "}
@ -1049,10 +1086,8 @@ export function GreenInnovationPage() {
)}
</div>
</div>
{/* Details column - show total count */}
</div>
</div>
</div> */}
</Card>
</div>