diff --git a/app/components/dashboard/project-management/product-innovation-page.tsx b/app/components/dashboard/project-management/product-innovation-page.tsx index da18932..0e64255 100644 --- a/app/components/dashboard/project-management/product-innovation-page.tsx +++ b/app/components/dashboard/project-management/product-innovation-page.tsx @@ -21,6 +21,8 @@ import toast from "react-hot-toast"; import { Badge } from "~/components/ui/badge"; import { Button } from "~/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card"; +import { MetricCard } from "~/components/ui/metric-card"; +import { BaseCard } from "~/components/ui/base-card"; import { Checkbox } from "~/components/ui/checkbox"; import { Bar, BarChart, LabelList } from "recharts" import { @@ -608,25 +610,25 @@ export function ProductInnovationPage() { 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 underline underline-offset-4 font-ligth text-base hover:bg-emerald-500/20 p-2 h-auto" > جزئیات بیشتر ); case "project_no": return ( - + {String(value)} ); case "title": - return {String(value)}; + return {String(value)}; case "project_status": return ( -
+
{formatNumber(String(value))} ); default: - return {String(value) || "-"}; + return {String(value) || "-"}; } }; @@ -670,87 +672,86 @@ export function ProductInnovationPage() {
{/* Stats Grid */}
- {loading || statsLoading - ? // Loading skeleton for stats cards - matching new design - Array.from({ length: 3 }).map((_, index) => ( - - -
-
-
-
-
+ {loading || statsLoading ? ( + // Loading skeleton for stats cards - matching new design + Array.from({ length: 3 }).map((_, index) => ( + + +
+
+
+
+
+
+
+
+
+
+
+
+ + + )) + ) : ( + <> + {/* First card (Metric/Matrix style) - span two columns */} +
+
-
-
-
-
-
+ + {/* Second card */} +
+ +
+
+
+

{stateCard.newProductExports.value}

+
{stateCard.newProductExports.description}
+
+
+
+
- - - )) - : Object.entries(stateCard).map(([key, card], index) => ( - - -
-
-

- {card.title} -

-
+ + {/* Third card - basic BaseCard */} +
+ +
+
+
+

{stateCard.impactOnImports.value}

+
{stateCard.impactOnImports.description}
+
+
+
+
-
-
-

- {card.value} - -

-

- {card.description} -

-
- {card?.percent && /} - {card?.percent &&
-

- {card?.percent} - -

-

- {card.descriptionPercent} -

-
} -
- - - ))} + + )}
{/* Funnel Chart */} - + ( {column.sortable ? ( @@ -891,10 +892,10 @@ export function ProductInnovationPage() { {/* Footer */} -
+
-
+
کل پروژه ها :{formatNumber(stats?.count_innovation_construction_inside_projects)}
@@ -907,8 +908,8 @@ export function ProductInnovationPage() {
-
میانگین :‌
-
+
میانگین :‌
+
{formatNumber( ((stats.average_project_score ?? 0) as number).toFixed?.(1) ?? 0 )} @@ -924,7 +925,7 @@ export function ProductInnovationPage() { - + شرح پروژه @@ -934,17 +935,17 @@ export function ProductInnovationPage() {
{/* Stats Cards */}
-

{selectedProjectDetails?.title}

+

{selectedProjectDetails?.title}

{selectedProjectDetails?.project_description}

{/* Technical Knowledge */}
-

دانش فنی محصول جدید

+

دانش فنی محصول جدید

- توسعه درونزا + توسعه درونزا
- همکاری فناورانه + همکاری فناورانه
- سایر + سایر -

+

استانداردهای ملی و بین‌المللی اخذ شده

@@ -985,7 +986,7 @@ export function ProductInnovationPage() { ).map((standard, index) => (
- {standard} + {standard}
))}
@@ -997,21 +998,21 @@ export function ProductInnovationPage() {
{/* Knowledge-based Certificate Button */} -
+
{selectedProjectDetails?.knowledge_based_certificate_obtained === "خیر" ? ( -
-
) : ( - + @@ -1070,237 +1071,89 @@ export function ProductInnovationPage() {
) : (
- {/* Project Description */} -
- - -
-
-

- میزان صادارت محصول جدید -

- -
- -
-

- {formatNumber(Math.round(popupStats?.new_products_export > 0 ? popupStats?.new_products_export : 0)) || formatNumber(0)} -

-

- میلیون ریال -

-
- / -
-

- {formatNumber(Math.round(popupStats?.new_products_export_percent > 0 ? popupStats?.new_products_export_percent : 0)) || formatNumber(0)}% -

-

- درصد به کل صادرات -

-
-
-
-
+ {/* Project Description - two MetricCards side by side */} +
+ 0 ? popupStats?.new_products_export : 0)} + percentValue={Math.round(popupStats?.new_products_export_percent > 0 ? popupStats?.new_products_export_percent : 0)} + valueLabel="میلیون ریال" + percentLabel="درصد به کل صادرات" + /> - - -
-
-

- تاثیر در واردات -

- -
- -
-

- {formatNumber(Math.round(popupStats?.import_impact > 0 ? popupStats?.import_impact : 0)) || formatNumber(0)} -

-

- میلیون ریال -

-
- / -
-

- {formatNumber(Math.round(popupStats?.import_impact_percent > 0 ? popupStats?.import_impact_percent : 0)) || formatNumber(0)}% -

-

- درصد صرفه جویی -

-
-
-
-
+ 0 ? popupStats?.import_impact : 0)} + percentValue={Math.round(popupStats?.import_impact_percent > 0 ? popupStats?.import_impact_percent : 0)} + valueLabel="میلیون ریال" + percentLabel="درصد صرفه جویی" + /> +
- - -
- - {/* Export Revenue Bar Chart */} -
-

ظرفیت صادر شده

-
- {popupLoading ? ( -
-
در حال بارگذاری...
-
- ) : exportChartData.length > 0 ? ( - - - - `${value.split(" ")[0]} ${formatNumber(value.split(" ")[1]).replaceAll('٬','')}`} - /> - `${formatNumber(value)} میلیون`}/> - - `${formatNumber(value)}`} - position="top" - offset={15} - fill="F9FAFB" - className="fill-foreground" - fontSize={16} + {/* Export Revenue Bar Chart */} +
+

ظرفیت صادر شده

+
+ {exportChartData.length > 0 ? ( + + + + `${value.split(" ")[0]} ${formatNumber(value.split(" ")[1]).replaceAll('٬','')}`} + fontSize={11} /> - - - - - ) : ( -
- داده‌ای برای نمایش وجود ندارد -
- )} -
-
+ `${formatNumber(value)} میلیون`} /> + + `${formatNumber(value)}`} position="top" offset={15} fill="F9FAFB" className="fill-foreground" fontSize={16} /> + +
+
+ ) : ( +
داده‌ای برای نمایش وجود ندارد
+ )} +
+
- {/* Export Revenue Line Chart */} -
-

ظرفیت صادر شده

-
- {popupLoading ? ( -
-
در حال بارگذاری...
-
- ) : allExportData.length > 0 ? ( - - - - ( - - - {payload.value} - - - )} - /> - `${formatNumber(value)} میلیون`} // 👈 اضافه کردن M کنار اعداد - /> - - `${formatNumber(value)} میلیون`} - contentStyle={{ - backgroundColor: "#1F2937", - border: "1px solid #374151", - borderRadius: "6px", - padding: "6px 10px", - fontSize: "11px", - color: "#F9FAFB", - }} - /> - - - {[...new Set(allExportData.map((item) => item.product_title))] - .slice(0, 5) - .map((product, index) => { - const colors = ["#10B981", "#EF4444", "#3B82F6", "#F59E0B", "#8B5CF6"]; - return ( - - ); - })} - - - - ) : ( -
- داده‌ای برای نمایش وجود ندارد -
- )} + {/* Export Revenue Line Chart */} +
+

ظرفیت صادر شده

+
+ {allExportData.length > 0 ? ( + + + + ( + + {(payload as any).value} + + )} /> + `${formatNumber(value)} میلیون`} /> + `${formatNumber(value)} میلیون`} contentStyle={{ backgroundColor: "#1F2937", border: "1px solid #374151", borderRadius: "6px", padding: "6px 10px", fontSize: "11px", color: "#F9FAFB" }} /> + + {[...new Set(allExportData.map((item) => item.product_title))].slice(0, 5).map((product, index) => { + const colors = ["#10B981", "#EF4444", "#3B82F6", "#F59E0B", "#8B5CF6"]; + return ; + })} + + + ) : ( +
داده‌ای برای نمایش وجود ندارد
+ )} +
-
- )} + )}
diff --git a/app/components/ui/funnel-chart.tsx b/app/components/ui/funnel-chart.tsx index 87e4e83..2327755 100644 --- a/app/components/ui/funnel-chart.tsx +++ b/app/components/ui/funnel-chart.tsx @@ -24,18 +24,18 @@ export function FunnelChart({ data, title, className = "" }: FunnelChartProps) { return (
{title && ( -

+

{title}

)} -
+
{/* Start Process Line */} -
-
ابتدا فرآیند
+
+
ابتدا فرآیند
-
۱۰۰%
+
۱۰۰%
@@ -50,7 +50,7 @@ export function FunnelChart({ data, title, className = "" }: FunnelChartProps) { return (
-
+
{item.label}
@@ -60,7 +60,7 @@ export function FunnelChart({ data, title, className = "" }: FunnelChartProps) { className="bg-[#3BC47A] h-8 rounded-2xl flex items-center justify-center text-lg relative" style={{ width: `${barWidth}%` }} > - + {item.value.toLocaleString('fa-IR')}
@@ -73,15 +73,15 @@ export function FunnelChart({ data, title, className = "" }: FunnelChartProps) {
{/* End Process Line */} -
-
انتها فرآیند
+
+
انتها فرآیند
{(() => { const lastValue = data[data.length - 1]?.value ?? 0; const percent = toPercent(lastValue); return (
-
{formatNumber(percent)}%
+
{formatNumber(percent)}%