inogen/app/components/ecosystem/info-panel.tsx
Saeed 40b5ad6e3c
Setup technology ecosystem page with network graph (#2)
* Add ecosystem page with network graph and company info panel

Co-authored-by: sd.eed1381 <sd.eed1381@gmail.com>

* Add unpaid company highlighting to network graph with toggle

Co-authored-by: sd.eed1381 <sd.eed1381@gmail.com>

* fix id something

* remove the useless files

* update the graph

* update the graph,fix the api ,also add some style and filters

* Refactor process impacts chart to use new CustomBarChart component (#3)

Co-authored-by: Cursor Agent <cursoragent@cursor.com>

* fix somestyle , add charts in ecosystem

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2025-08-16 16:48:15 +03:30

170 lines
6.0 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import React, { useEffect, useState } from "react";
import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card";
import {
Area,
AreaChart,
Bar,
CartesianGrid,
ResponsiveContainer,
Tooltip,
XAxis,
YAxis,
} from "recharts";
import { CustomBarChart } from "~/components/ui/custom-bar-chart";
import apiService from "~/lib/api";
export interface InfoPanelProps {
selectedCompany: { id: string; label?: string } | null;
}
interface EcosystemCounts {
knowledge_based_count: string;
consultant_count: string;
startup_count: string;
innovation_center_count: string;
accelerator_count: string;
university_count: string;
fund_count: string;
company_count: string;
actor_count: string;
mou_count: string;
}
export function InfoPanel({ selectedCompany }: InfoPanelProps) {
const [counts, setCounts] = useState<EcosystemCounts | null>(null);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
const fetchCounts = async () => {
setIsLoading(true);
try {
const res = await apiService.callInnovationProcess<EcosystemCounts>({
ecosystem_counts_function: {},
});
setCounts(res.data);
} catch (err) {
console.error("Failed to fetch ecosystem counts:", err);
} finally {
setIsLoading(false);
}
};
fetchCounts();
}, []);
const title = selectedCompany?.label || "نمای کلی";
const subTitle = selectedCompany ? `شناسه: ${selectedCompany.id}` : "انتخابی انجام نشده است";
// Transform counts into chart-friendly data
const barData =
counts && !selectedCompany
? [
{ name: "دانش بنیان", value: +counts.knowledge_based_count },
{ name: "مشاور", value: +counts.consultant_count },
{ name: "استارتاپ", value: +counts.startup_count },
{ name: "مرکز نوآوری", value: +counts.innovation_center_count },
{ name: "شتابدهنده", value: +counts.accelerator_count },
{ name: "دانشگاه", value: +counts.university_count },
{ name: "صندوق", value: +counts.fund_count },
{ name: "شرکت", value: +counts.company_count },
]
: [];
const lineData = [
{ month: "01", value: 3 },
{ month: "02", value: 6 },
{ month: "03", value: 4 },
{ month: "04", value: 9 },
{ month: "05", value: 7 },
{ month: "06", value: 11 },
];
return (
<div className="space-y-4 min-h-full">
<Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)]">
<CardHeader className="pb-2">
<CardTitle className="font-persian text-base">{title}</CardTitle>
<div className="text-xs text-gray-400 font-persian">{subTitle}</div>
</CardHeader>
<CardContent>
{isLoading ? (
<div className="text-sm text-gray-300 font-persian">در حال بارگذاری...</div>
) : selectedCompany ? (
<div className="text-sm text-gray-300 font-persian">
این یک باکس اطلاعات نمونه است. پس از دریافت API، جزئیات شرکت نمایش داده میشود.
</div>
) : counts ? (
<div className="space-y-4 text-sm text-gray-300 font-persian">
<div className="grid grid-cols-2 gap-4">
<div>
<span className="font-bold">تعداد بازیگران اکوسیستم: </span>
{counts.actor_count}
</div>
<div>
<span className="font-bold">تعداد تفاهم نامه ها: </span>
{counts.mou_count}
</div>
</div>
{/* Grid for categories */}
<div className="grid grid-cols-2 gap-4">
<div>دانش بنیان: {counts.knowledge_based_count}</div>
<div>مشاور: {counts.consultant_count}</div>
<div>استارتاپ: {counts.startup_count}</div>
<div>مرکز نوآوری: {counts.innovation_center_count}</div>
<div>شتابدهنده: {counts.accelerator_count}</div>
<div>دانشگاه: {counts.university_count}</div>
<div>صندوق: {counts.fund_count}</div>
<div>شرکت: {counts.company_count}</div>
</div>
</div>
) : (
<div className="text-sm text-gray-300 font-persian">خطا در بارگذاری دادهها.</div>
)}
</CardContent>
{/* Bar Chart Section */}
<div className="h-56">
<CardHeader className="pb-0">
<CardTitle className="font-persian text-sm">
{selectedCompany ? "نمودار میله‌ای" : "نمودار تعداد بر اساس دسته‌بندی"}
</CardTitle>
</CardHeader>
<CardContent className="h-[180px]">
{barData.length > 0 && (
<CustomBarChart data={barData} dataKey="value" labelKey="name" />
)}
</CardContent>
</div>
{/* Line/Area Chart Section */}
<div className="h-56">
<CardHeader className="pb-0">
<CardTitle className="font-persian text-sm">روند نمونه</CardTitle>
</CardHeader>
<CardContent className="h-[180px]">
<ResponsiveContainer width="100%" height="100%">
<AreaChart data={lineData}>
<CartesianGrid strokeDasharray="3 3" stroke="rgba(255,255,255,0.1)" />
<XAxis dataKey="month" />
<YAxis />
<Tooltip />
<Area
type="monotone"
dataKey="value"
stroke="#34d399"
fill="rgba(52, 211, 153, 0.25)"
/>
</AreaChart>
</ResponsiveContainer>
</CardContent>
</div>
</Card>
</div>
);
}
export default InfoPanel;