feat: finish internal-innovation

This commit is contained in:
MehrdadAdabi 2025-09-04 16:40:26 +03:30
parent 73f960b56a
commit ec6235f00c

View File

@ -53,19 +53,19 @@ interface innovationBuiltInDate {
interface DialogInfo { interface DialogInfo {
WorkflowID: number WorkflowID: number
collaboration_model: string; // مشارکت استراتژیک collaboration_model: string;
complexity_level: string; // فناوری سطح متوسط complexity_level: string;
developer_team_role: string; // نظارت developer_team_role: string;
number_employees_involved: number | null; // ممکن است null باشد number_employees_involved: number | null;
participants_full_name: string; // مریم احمدی participants_full_name: string;
project_description: string; // توضیحات پروژه project_description: string;
project_id: string; // "20922" project_id: string;
project_no: string; // "13" project_no: string;
project_rating: string; // "68" (اگر میخوای عدد باشد: number) project_rating: string;
project_status: string; // پروپوزال project_status: string;
role_company_staff: string | null; // ممکن است null باشد role_company_staff: string | null;
technology_maturity_level: string; // مرحله بلوغ technology_maturity_level: string;
title: string; // عنوان پروژه title: string;
technology_params?: Array<TechnologyParameter> technology_params?: Array<TechnologyParameter>
} }
@ -165,11 +165,11 @@ const columns = [
{ key: "details", label: "جزئیات پروژه", sortable: false, width: "140px" }, { key: "details", label: "جزئیات پروژه", sortable: false, width: "140px" },
]; ];
const data = [ const dialogChartData = [
{ name: 'افول', value: 10 }, { name: 'مرحله افول', value: 10 },
{ name: 'رشد', value: 20 }, { name: 'مرحله رشد', value: 20 },
{ name: 'بلوغ', value: 15 }, { name: 'مرحله بلوغ', value: 15 },
{ name: عرفی', value: 25 }, { name: رحه پیدایش', value: 25 },
]; ];
@ -269,7 +269,6 @@ export function InnovationBuiltInsidePage() {
const handleProjectDetails = async (project: DialogInfo) => { const handleProjectDetails = async (project: DialogInfo) => {
setShowDialogItems(true) setShowDialogItems(true)
setDetailsDialogOpen(true); setDetailsDialogOpen(true);
setSelectedProjectDetails(project); setSelectedProjectDetails(project);
await fetchDialogTbl(project.WorkflowID) await fetchDialogTbl(project.WorkflowID)
setTimeout(() => { setTimeout(() => {
@ -427,7 +426,11 @@ export function InnovationBuiltInsidePage() {
useEffect(() => { useEffect(() => {
fetchProjects(true); fetchProjects(true);
fetchStats(); fetchStats();
}, [sortConfig, selectedProjects]); }, [sortConfig]);
useEffect(() => {
fetchStats();
}, [selectedProjects])
useEffect(() => { useEffect(() => {
if (currentPage > 1) { if (currentPage > 1) {
@ -478,6 +481,7 @@ export function InnovationBuiltInsidePage() {
const fetchStats = async () => { const fetchStats = async () => {
try { try {
detailsDialogOpen
setStatsLoading(true); setStatsLoading(true);
const raw = await apiService.call<any>({ const raw = await apiService.call<any>({
innovation_construction_inside_function: { innovation_construction_inside_function: {
@ -691,7 +695,7 @@ export function InnovationBuiltInsidePage() {
{/* Stats Cards */} {/* Stats Cards */}
<div className="flex gap-6 w-full"> <div className="flex gap-6 w-full">
<div className="flex flex-col justify-between w-full gap-6"> <div className="flex flex-col justify-between w-full gap-6">
{loading || statsLoading {statsLoading
? // Loading skeleton for stats cards - matching new design ? // Loading skeleton for stats cards - matching new design
Array.from({ length: 2 }).map((_, index) => ( Array.from({ length: 2 }).map((_, index) => (
<Card <Card
@ -758,7 +762,7 @@ export function InnovationBuiltInsidePage() {
{ {
loading ? <div className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] rounded-lg backdrop-blur-sm border border-gray-700/50 animate-pulse"> statsLoading ? <div className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] rounded-lg backdrop-blur-sm border border-gray-700/50 animate-pulse">
<div className="p-0 h-full"> <div className="p-0 h-full">
<div className="flex flex-col justify-between gap-2 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 p-4 px-5"> <div className="flex justify-between items-center border-b-2 border-gray-500/20 p-4 px-5">
@ -832,7 +836,7 @@ export function InnovationBuiltInsidePage() {
} }
{ {
loading ? <div className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] h-30 rounded-lg backdrop-blur-sm border border-gray-700/50 animate-pulse mt-4"> statsLoading ? <div className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] h-30 rounded-lg backdrop-blur-sm border border-gray-700/50 animate-pulse mt-4">
<div className="h-full flex flex-row justify-between p-6 items-center w-4/5 m-auto"> <div className="h-full flex flex-row justify-between p-6 items-center w-4/5 m-auto">
<div className="h-6 w-32 bg-gray-600/40 rounded-md"></div> <div className="h-6 w-32 bg-gray-600/40 rounded-md"></div>
<div className="h-8 w-16 bg-gray-600/40 rounded-md"></div> <div className="h-8 w-16 bg-gray-600/40 rounded-md"></div>
@ -1088,7 +1092,7 @@ export function InnovationBuiltInsidePage() {
<SquareUser className="text-emerald-500 w-5" /> <SquareUser className="text-emerald-500 w-5" />
<div className="flex flex-row justify-between w-full"> <div className="flex flex-row justify-between w-full">
<span>نقش کارکنان شرکت: </span> <span>نقش کارکنان شرکت: </span>
<span>نظارت کننده</span> <span>{selectedProjectDetails?.role_company_staff ?? '-'}</span>
</div> </div>
</div> </div>
<div className="flex flex-row gap-2 w-full"> <div className="flex flex-row gap-2 w-full">
@ -1139,11 +1143,11 @@ export function InnovationBuiltInsidePage() {
return <div className="grid grid-cols-3 py-3" key={`technology-${index}-${el.WorkflowID}`}> return <div className="grid grid-cols-3 py-3" key={`technology-${index}-${el.WorkflowID}`}>
<span className="text-center">{el.technology_parameter_title}</span> <span className="text-center">{el.technology_parameter_title}</span>
<div className="flex flex-row items-center gap-1 justify-center"> <div className="flex flex-row items-center gap-1 justify-center">
<span>{el.domestic_technology_parameter_value}</span> <span>{formatNumber(el.domestic_technology_parameter_value)}</span>
<span className="text-sm text-gray-400">میلیون لیتر</span> <span className="text-sm text-gray-400">میلیون لیتر</span>
</div> </div>
<div className="flex flex-row items-center gap-1 justify-center"> <div className="flex flex-row items-center gap-1 justify-center">
<span>{el.foreign_technology_parameter_value}</span> <span>{formatNumber(el.foreign_technology_parameter_value)}</span>
<span className="text-sm text-gray-400">میلیون لیتر</span> <span className="text-sm text-gray-400">میلیون لیتر</span>
</div> </div>
</div> </div>
@ -1182,42 +1186,59 @@ export function InnovationBuiltInsidePage() {
))} ))}
</div> : <ResponsiveContainer width="100%" height={420}> </div> : <ResponsiveContainer width="100%" height={420}>
<LineChart <LineChart
data={data} data={dialogChartData}
margin={{ top: 20, right: 20, left: 20, bottom: 80 }} margin={{ top: 20, right: 20, left: 20, bottom: 80 }}
> >
<XAxis <XAxis
dataKey="name" dataKey="name"
interval={0} interval={0}
padding={{ right: 10 }} padding={{ right: 15, left: 15 }}
axisLine={false} axisLine={false}
tick={{ fill: "white" }} tick={{ fill: "white" }}
fontSize={13}
/> />
<Line type="monotone" dataKey="value" stroke="#ff4d6d" strokeWidth={2} dot={false} /> <Line
type="monotone"
dataKey="value"
stroke="#ff4d6d"
strokeWidth={2}
dot={false}
/>
<ReferenceLine x="بلوغ" stroke="#00bc7c" strokeWidth={2} /> <ReferenceLine
x={selectedProjectDetails?.technology_maturity_level}
stroke="#00bc7c"
strokeWidth={2}
/>
<Customized <Customized
component={(props: any) => { component={(props: any) => {
const { xAxisMap, width, height } = props; const { xAxisMap, width, height } = props;
const xAxes = Object.values(xAxisMap || {}); const xAxes = Object.values(xAxisMap || {});
if (!xAxes.length) return null; if (!xAxes.length) return null;
const xAxis: any = xAxes[0]; const xAxis: any = xAxes[0];
const ticks = xAxis?.ticks || []; const ticks = xAxis?.ticks || [];
const tick = ticks.find((t: any) => {
return t && (t.value === "بلوغ" || (t.payload && t.payload.value === "بلوغ"));
});
const x = (tick && tick.coordinate) ?? width / 2 + 80 const value = selectedProjectDetails?.technology_maturity_level;
const xFromScale = typeof xAxis?.scale === "function" ? xAxis.scale(value) : undefined;
const tick = ticks.find(
(t: any) =>
t &&
(t.value === value || (t.payload && t.payload.value === value))
);
const axisOffsetX = xAxis?.x ?? 0;
const x = (xFromScale ?? tick?.coordinate ?? width / 2) + axisOffsetX - 15;
const rectWidth = 140; const rectWidth = 140;
const rectHeight = 28; const rectHeight = 28;
const rectX = x - rectWidth / 2; const rectX = x - rectWidth / 2;
const axisHeight = xAxis?.height ?? 40; const axisHeight = xAxis?.height ?? 40;
const rectY = (height - axisHeight) - 30; const rectY = height - axisHeight - 30;
return ( return (
<g> <g>
<rect <rect
@ -1247,10 +1268,6 @@ export function InnovationBuiltInsidePage() {
</LineChart> </LineChart>
</ResponsiveContainer> </ResponsiveContainer>
} }
</div> </div>
</div> </div>