diff --git a/app/components/dashboard/project-management/product-innovation-page.tsx b/app/components/dashboard/project-management/product-innovation-page.tsx index 962df80..da18932 100644 --- a/app/components/dashboard/project-management/product-innovation-page.tsx +++ b/app/components/dashboard/project-management/product-innovation-page.tsx @@ -22,7 +22,13 @@ import { Badge } from "~/components/ui/badge"; import { Button } from "~/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card"; import { Checkbox } from "~/components/ui/checkbox"; -import { CustomBarChart } from "~/components/ui/custom-bar-chart"; +import { Bar, BarChart, LabelList } from "recharts" +import { + Popover, + PopoverTrigger, + PopoverContent, +} from "~/components/ui/popover" + import { FunnelChart } from "~/components/ui/funnel-chart"; import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from "recharts"; import { @@ -43,9 +49,10 @@ import { TableRow, } from "~/components/ui/table"; import apiService from "~/lib/api"; -import { formatNumber } from "~/lib/utils"; +import { formatNumber, handleDataValue } from "~/lib/utils"; import { DashboardLayout } from "../layout"; import { Skeleton } from "~/components/ui/skeleton"; +import { Tooltip as TooltipSh, TooltipTrigger, TooltipContent } from "~/components/ui/tooltip"; moment.loadPersian({ usePersianDigits: true }); @@ -130,7 +137,57 @@ const columns = [ { key: "details", label: "جزئیات پروژه", sortable: false, width: "140px" }, ]; + +export default function Timeline() { + const stages = ["تجاری سازی", "توسعه", "تحلیل بازار", "ثبت ایده"]; + const currentStage = 1; // index of current stage + + return ( +
+ {/* Year labels */} +
+ ۱۴۰۷ + ۱۴۰۶ + ۱۴۰۵ + ۱۴۰۴ +
+ + {/* Timeline bar */} +
+ {stages.map((stage, index) => ( +
+ + +
+ {stage} +
+
+
+
+ ))} + + {/* Vertical line showing current position */} +
+
وضعیت فعلی
+
+
+ ); +} + + + export function ProductInnovationPage() { + const [showPopup, setShowPopup] = useState(false); const [projects, setProjects] = useState([]); const [loading, setLoading] = useState(false); const [loadingMore, setLoadingMore] = useState(false); @@ -138,7 +195,6 @@ export function ProductInnovationPage() { const [pageSize] = useState(20); const [hasMore, setHasMore] = useState(true); const [totalCount, setTotalCount] = useState(0); - const [actualTotalCount, setActualTotalCount] = useState(0); const [statsLoading, setStatsLoading] = useState(false); const [stats, setStats] = useState({ new_products_revenue_share: 0, @@ -199,28 +255,30 @@ export function ProductInnovationPage() { const observerRef = useRef(null); const fetchingRef = useRef(false); + const handleProjectDetails = async (project: ProductInnovationData) => { setSelectedProjectDetails(project); + console.log(project) setDetailsDialogOpen(true); - await fetchPopupData(project.project_id); + await fetchPopupData(project); }; - const fetchPopupData = async (projectId: string) => { + const fetchPopupData = async (project: ProductInnovationData) => { try { setPopupLoading(true); // Fetch popup stats const statsResponse = await apiService.call({ innovation_product_popup_function1: { - project_id: projectId + project_id: project.project_id } }); if (statsResponse.state === 0) { const statsData = JSON.parse(statsResponse.data); if (statsData.innovation_product_popup_function1 && statsData.innovation_product_popup_function1[0]) { - setPopupStats(statsData.innovation_product_popup_function1[0]); + setPopupStats(JSON.parse(statsData.innovation_product_popup_function1)[0]); } } @@ -234,17 +292,16 @@ export function ProductInnovationPage() { ], GroupBy: ["product_title", "full_season"] }); - if (chartResponse.state === 0) { const chartData = JSON.parse(chartResponse.data); if (Array.isArray(chartData)) { // Set all data for line chart - setAllExportData(chartData); - + // Filter data for the selected project (bar chart) const filteredData = chartData.filter(item => - item.product_title === selectedProjectDetails?.title + item.product_title === project?.title ); + setAllExportData(chartData); setExportChartData(filteredData); } } @@ -486,16 +543,15 @@ export function ProductInnovationPage() { // Transform data for line chart const transformDataForLineChart = (data: any[]) => { - const seasons = [...new Set(data.map(item => item.full_season))].sort(); + const seasons = [...new Set(data.map(item => item.full_season))]; const products = [...new Set(data.map(item => item.product_title))]; - return seasons.map(season => { const seasonData: any = { season }; products.forEach(product => { const productData = data.find(item => item.product_title === product && item.full_season === season ); - seasonData[product] = productData ? Math.round(productData.export_revenue_sum / 1000000) : 0; + seasonData[product] = productData?.export_revenue_sum > 0 && productData ? Math.round(productData?.export_revenue_sum) : 0; }); return seasonData; }); @@ -550,7 +606,8 @@ export function ProductInnovationPage() { +
+ ) : ( + + + + + + + + +
+

+ شماره گواهی: + {selectedProjectDetails?.knowledge_based_certificate_number || + "—"} +

+

+ تاریخ اخذ: + {handleDataValue(selectedProjectDetails?.certificate_obtain_date) || "—"} +

+

+ مرجع صادرکننده: + {selectedProjectDetails?.issuing_authority || "—"} +

+
+
+
+
+
+ )} + + -
{/* Left Column - Project Description and Charts */} -
+ {popupLoading ? ( +
+
+ + + + + + + + + + +
+
+ + +
+
+ + +
+
+ ) : ( +
{/* Project Description */} -
-

- {selectedProjectDetails?.title} -

-

- {selectedProjectDetails?.project_description || "-"} -

- - {/* Project Timeline */} -
-
- ۱۴۰۴ - ۱۴۰۵ - ۱۴۰۶ - ۱۴۰۷ -
-
-
-
- ثبت ایده -
-
-
-
- تحلیل بازار -
-
-
-
- توسعه -
-
-
-
- تجاری سازی -
-
-
وضعیت فعلی: تحلیل بازار
-
+
+ + +
+
+

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

+ +
+ +
+

+ {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)}% +

+

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

+
+
+
+
+ + + +
+
+

+ تاثیر در واردات +

+ +
+ +
+

+ {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)}% +

+

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

+
+
+
+
+ + +
{/* Export Revenue Bar Chart */} -
-

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

-
+
+

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

+
{popupLoading ? (
-
در حال بارگذاری...
+
در حال بارگذاری...
) : exportChartData.length > 0 ? ( - { - // Sort by season order - const seasonOrder = ['بهار', 'تابستان', 'پاییز', 'زمستان']; - const getSeasonIndex = (season: string) => { - const year = season.split(' ')[1]; - const seasonName = season.split(' ')[0]; - return parseInt(year) * 4 + seasonOrder.indexOf(seasonName); - }; - return getSeasonIndex(a.full_season) - getSeasonIndex(b.full_season); - }) - .map(item => ({ - label: item.full_season, - value: Math.round(item.export_revenue_sum / 1000000), // Convert to millions - color: "bg-emerald-400", - labelColor: "text-white" - }))} - barHeight="h-6" - showAxisLabels={true} + + + + `${value.split(" ")[0]} ${formatNumber(value.split(" ")[1]).replaceAll('٬','')}`} /> + `${formatNumber(value)} میلیون`}/> + + `${formatNumber(value)}`} + position="top" + offset={15} + fill="F9FAFB" + className="fill-foreground" + fontSize={16} + /> + + + + ) : (
داده‌ای برای نمایش وجود ندارد @@ -944,52 +1208,90 @@ export function ProductInnovationPage() {
{/* Export Revenue Line Chart */} -
-

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

-
+
+

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

+
{popupLoading ? ( -
-
در حال بارگذاری...
+
+
در حال بارگذاری...
) : allExportData.length > 0 ? ( - - - - - - - {[...new Set(allExportData.map(item => item.product_title))].slice(0, 5).map((product, index) => { - const colors = ['#10B981', '#EF4444', '#3B82F6', '#F59E0B', '#8B5CF6']; + + + ( + + + {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 ( ); })} - - + + + ) : (
داده‌ای برای نمایش وجود ندارد @@ -998,114 +1300,9 @@ export function ProductInnovationPage() {
+ )} - {/* Right Column - Stats Cards and Details */} -
- {/* Stats Cards */} -
-
-

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

- {popupLoading ? ( -
-
-
-
-
- ) : ( - <> -
- {formatNumber(popupStats.new_products_export)} -
-
میلیون ریال
-
- {formatNumber(popupStats.new_products_export_percent)}% -
-
درصد به کل صادرات
- - )} -
- -
-

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

- {popupLoading ? ( -
-
-
-
-
- ) : ( - <> -
- {formatNumber(popupStats.import_impact)} -
-
میلیون ریال
-
- {formatNumber(popupStats.import_impact_percent)}% -
-
درصد صرفه جویی
- - )} -
-
- - {/* Technical Knowledge */} -
-

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

-
-
- - توسعه درونزا -
-
- - همکاری فناورانه -
-
- - سایر -
-
-
- - {/* Standards */} -
-

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

-
-
-
- استاندارد ملی شماره یک -
-
-
- استاندارد بین المللی شماره یک -
-
-
- استاندارد ملی شماره یک -
-
-
- استاندارد ملی شماره یک -
-
-
- - {/* Knowledge-based Certificate Button */} -
- -
-
+
diff --git a/app/components/dashboard/sidebar.tsx b/app/components/dashboard/sidebar.tsx index 4a90072..172a6dd 100644 --- a/app/components/dashboard/sidebar.tsx +++ b/app/components/dashboard/sidebar.tsx @@ -217,6 +217,7 @@ export function Sidebar({ if (item.id === "strategic-alignment") { return (