finish:digital-inovation page

This commit is contained in:
MehrdadAdabi 2025-08-26 17:23:41 +03:30
parent b06e569e39
commit c23e82604e
2 changed files with 105 additions and 74 deletions

View File

@ -91,14 +91,29 @@ enum DigitalCardLabel {
decreaseEnergy = "کاهش مصرف انرژی",
}
enum projectStatus {
propozal = "پروپوزال",
contract = "پیشنویس قرارداد",
inprogress = "در حال انجام",
stop = "متوقف شده",
mafasa = "مرحله مفاصا",
finish = "پایان یافته",
}
interface ProcessInnovationData {
project_no: string;
title: string;
project_status: string;
project_rating: string;
project_description: string;
total_project: number;
WorkflowID: number;
desired_strategy: string;
digital_capability: string;
digital_competence: string;
digital_puberty_elements: string;
innovation_cost_reduction: number | string;
operational_plan: string;
originality_digital_solution: string;
project_description: string;
project_no: string;
project_rating: number | string;
project_status: string;
reduce_costs_percent: number;
title: string;
}
interface HouseItem {
@ -162,8 +177,7 @@ export function DigitalInnovationPage() {
new Set()
);
const [detailsDialogOpen, setDetailsDialogOpen] = useState(false);
// const [selectedProjectDetails, setSelectedProjectDetails] =
// useState<ProcessInnovationData | null>(null);
const [avarage, setAvarage] = useState<number>(0);
const observerRef = useRef<HTMLDivElement>(null);
const fetchingRef = useRef(false);
@ -194,7 +208,6 @@ export function DigitalInnovationPage() {
return new Intl.NumberFormat("fa-IR").format(numericValue);
};
// Stats cards data - computed from projects data
const statsCards: StatsCard[] = [
{
id: "production-stops-prevention",
@ -268,9 +281,9 @@ export function DigitalInnovationPage() {
"operational_plan",
"desired_strategy",
"innovation_cost_reduction",
"reduce_costs_percent"
"reduce_costs_percent",
],
Sorts: [["start_date", "asc"]],
Sorts: [[sortConfig.field, sortConfig.direction]],
Conditions: [["type_of_innovation", "=", "نوآوری دیجیتال"]],
Pagination: { PageNumber: pageToFetch, PageSize: pageSize },
});
@ -280,10 +293,11 @@ export function DigitalInnovationPage() {
const dataString = response.data;
if (dataString && typeof dataString === "string") {
try {
const parsedData = JSON.parse(dataString);
const parsedData: ProcessInnovationData = JSON.parse(dataString);
if (Array.isArray(parsedData)) {
if (reset) {
setProjects(parsedData);
calculateAverage(parsedData);
setTotalCount(parsedData.length);
} else {
setProjects((prev) => [...prev, ...parsedData]);
@ -331,6 +345,7 @@ export function DigitalInnovationPage() {
} finally {
setLoading(false);
setLoadingMore(false);
fetchingRef.current = false;
}
};
@ -385,6 +400,8 @@ export function DigitalInnovationPage() {
direction:
prev.field === field && prev.direction === "asc" ? "desc" : "asc",
}));
fetchTotalCount();
fetchStats();
setCurrentPage(1);
setProjects([]);
setHasMore(true);
@ -515,6 +532,30 @@ export function DigitalInnovationPage() {
}
}, [rating]);
const ststusColor = (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 renderCellContent = (item: any, column: any) => {
const value = item[column.key as keyof ProcessInnovationData];
@ -533,7 +574,7 @@ export function DigitalInnovationPage() {
variant="ghost"
size="sm"
onClick={() => handleProjectDetails(item)}
className="text-emerald-400 hover:text-emerald-300 hover:bg-emerald-500/20 p-2 h-auto"
className="text-emerald-400 hover:text-emerald-300 hover:bg-emerald-500/20 p-2 h-auto cursor-pointer"
>
جزئیات بیشتر
</Button>
@ -554,15 +595,16 @@ export function DigitalInnovationPage() {
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",
}}
>
<div className="flex items-center gap-1">
<Badge
variant={ststusColor(value)}
className="font-medium border-2 p-0 block w-2 h-2 rounded-full"
style={{
border: "none",
}}
></Badge>
{String(value)}
</Badge>
</div>
);
case "project_rating":
return (
@ -583,6 +625,14 @@ export function DigitalInnovationPage() {
}
};
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">
@ -700,7 +750,7 @@ export function DigitalInnovationPage() {
<Card className="bg-transparent backdrop-blur-sm rounded-2xl overflow-hidden w-full h-max">
<CardContent className="p-0">
<div className="relative">
<Table containerClassName="overflow-auto custom-scrollbar max-h-[calc(90vh-270px)]">
<Table containerClassName="overflow-auto custom-scrollbar h-[calc(90vh-270px)]">
<TableHeader>
<TableRow className="bg-[#3F415A]">
{columns.map((column) => (
@ -837,11 +887,7 @@ export function DigitalInnovationPage() {
میانگین امتیاز :
</div>
<div className="font-bold">
{formatNumber(
((stats.averageScore ?? 0) as number).toFixed?.(1) ??
stats.averageScore ??
0
)}
{formatNumber(((avarage ?? 0) as number).toFixed?.(1) ?? 0)}
</div>
</div>
</div>
@ -876,7 +922,7 @@ export function DigitalInnovationPage() {
</span>
</div>
<span className="text-sm text-gray-100">
شایستگی­ های کلیدی محدود
{dialogInfo?.digital_capability}
</span>
</div>
<div className="flex justify-between">
@ -887,7 +933,7 @@ export function DigitalInnovationPage() {
</span>
</div>
<span className="text-sm text-gray-100">
بدون تغییر کپی شده
{dialogInfo?.digital_competence}
</span>
</div>
<div className="flex justify-between">
@ -901,15 +947,15 @@ export function DigitalInnovationPage() {
</span>
</div>
<span className="text-sm text-gray-100">
دیجیتال کردن ارائه اطلاعات
{dialogInfo?.digital_puberty_elements}
</span>
</div>
</div>
</div>
</div>
<div className="digitalAbilityDevelopment flex flex-col gap-10 border-l-2 border-l-gray-600 pr-5">
<div className="digitalAbilityDevelopment flex flex-col gap-10 border-l-2 border-l-gray-600 px-5">
<div className="flex flex-col gap-4">
<span className="text-sm font-bold">
<span className="text-md font-bold">
توسعه قابلیت های دیجیتال:{" "}
</span>
<div className="flex flex-col gap-2">
@ -918,28 +964,16 @@ export function DigitalInnovationPage() {
size={"1.2rem"}
className="text-emerald-400"
/>
<span>قابلیت شماره یک </span>
</div>
<div className="flex gap-1.5">
<LoaderCircle
size={"1.2rem"}
className="text-emerald-400"
/>
<span>قابلیت شماره یک </span>
</div>
<div className="flex gap-1.5">
<LoaderCircle
size={"1.2rem"}
className="text-emerald-400"
/>
<span>قابلیت شماره یک </span>
<span className="text-sm">
{dialogInfo?.digital_capability}
</span>
</div>
</div>
</div>
<div className="flex flex-col gap-4">
<span className="text-sm font-bold">
توسعه قابلیت های دیجیتال:{" "}
<span className="text-md font-bold">
برنامه های عملیاتی مرتبط:
</span>
<div className="flex flex-col gap-2">
<div className="flex gap-1.5">
@ -947,27 +981,15 @@ export function DigitalInnovationPage() {
size={"1.2rem"}
className="text-emerald-400"
/>
<span>قابلیت شماره یک </span>
</div>
<div className="flex gap-1.5">
<LoaderCircle
size={"1.2rem"}
className="text-emerald-400"
/>
<span>قابلیت شماره یک </span>
</div>
<div className="flex gap-1.5">
<LoaderCircle
size={"1.2rem"}
className="text-emerald-400"
/>
<span>قابلیت شماره یک </span>
<span className="text-sm">
{dialogInfo?.operational_plan}
</span>
</div>
</div>
</div>
<div className="flex flex-col gap-4">
<span className="text-sm font-bold">
توسعه قابلیت های دیجیتال:{" "}
<span className="text-md font-bold">
استراتژی های مورد نظر:
</span>
<div className="flex flex-col gap-2">
<div className="flex gap-1.5">
@ -975,22 +997,24 @@ export function DigitalInnovationPage() {
size={"1.2rem"}
className="text-emerald-400"
/>
<span>قابلیت شماره یک </span>
<span className="text-sm">
{dialogInfo?.desired_strategy}
</span>
</div>
<div className="flex gap-1.5">
{/* <div className="flex gap-1.5">
<LoaderCircle
size={"1.2rem"}
className="text-emerald-400"
/>
<span>قابلیت شماره یک </span>
</div>
<div className="flex gap-1.5">
</div> */}
{/* <div className="flex gap-1.5">
<LoaderCircle
size={"1.2rem"}
className="text-emerald-400"
/>
<span>قابلیت شماره یک </span>
</div>
</div> */}
</div>
</div>
</div>
@ -1004,7 +1028,14 @@ export function DigitalInnovationPage() {
<div className="content p-4 flex flex-row-reverse gap-10 justify-center items-center">
<div className="flex flex-col gap-1">
<span className="text-emerald-400 font-bold text-3xl">
10%
%{" "}
{formatNumber(
(
Math.round(
dialogInfo?.reduce_costs_percent! * 100
) / 100
).toFixed(2)
)}
</span>
<span className="text-gray-500 text-sm font-normal">
درصد به کل هزینه ها
@ -1013,7 +1044,7 @@ export function DigitalInnovationPage() {
<b className="w-0.5 h-9 bg-gray-600 rotate-[35deg] rounded-full" />
<div className="flex flex-col gap-1">
<span className="text-emerald-400 text-3xl font-bold">
۱۰,۲۳۰
{formatNumber(+dialogInfo?.innovation_cost_reduction!)}
</span>
<span className="text-gray-500 text-sm font-normal">
میلیون ریال

View File

@ -11,7 +11,7 @@ const Table = React.forwardRef<HTMLTableElement, TableProps>(
<div className={cn("relative w-full", containerClassName)}>
<table
ref={ref}
className={cn("w-full caption-bottom text-sm", className)}
className={cn("w-full caption-bottom text-sm h-full", className)}
{...props}
/>
</div>