refactor and fix the styles in ecosystem and product-innovation
This commit is contained in:
parent
aed286660a
commit
58331eed7a
|
|
@ -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"
|
||||
>
|
||||
جزئیات بیشتر
|
||||
</Button>
|
||||
);
|
||||
case "project_no":
|
||||
return (
|
||||
<Badge variant="outline" className="font-mono">
|
||||
<Badge variant="outline" className="font-mono text-base font-light">
|
||||
{String(value)}
|
||||
</Badge>
|
||||
);
|
||||
case "title":
|
||||
return <span className="font-medium text-white">{String(value)}</span>;
|
||||
return <span className="font-light text-base text-white">{String(value)}</span>;
|
||||
case "project_status":
|
||||
return (
|
||||
<div className="flex items-center gap-1">
|
||||
<div className="flex items-center text-base font-light gap-1">
|
||||
<Badge
|
||||
variant={statusColor(value as projectStatus)}
|
||||
className="font-medium border-2 p-0 block w-2 h-2 rounded-full"
|
||||
className="font-semibold text-base border-2 p-0 block w-2 h-2 rounded-full"
|
||||
style={{
|
||||
border: "none",
|
||||
}}
|
||||
|
|
@ -638,13 +640,13 @@ export function ProductInnovationPage() {
|
|||
return (
|
||||
<Badge
|
||||
variant="outline"
|
||||
className={`text-lg text-center border-none mx-auto`}
|
||||
className={`font-semibold text-base text-center border-none mx-auto`}
|
||||
>
|
||||
{formatNumber(String(value))}
|
||||
</Badge>
|
||||
);
|
||||
default:
|
||||
return <span className="text-gray-300">{String(value) || "-"}</span>;
|
||||
return <span className="text-white text-base font-light">{String(value) || "-"}</span>;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -670,8 +672,8 @@ export function ProductInnovationPage() {
|
|||
<div className="space-y-6 w-full">
|
||||
{/* Stats Grid */}
|
||||
<div className="grid grid-cols-2 grid-rows-2 gap-5 h-full">
|
||||
{loading || statsLoading
|
||||
? // Loading skeleton for stats cards - matching new design
|
||||
{loading || statsLoading ? (
|
||||
// Loading skeleton for stats cards - matching new design
|
||||
Array.from({ length: 3 }).map((_, index) => (
|
||||
<Card
|
||||
key={`skeleton-${index}`}
|
||||
|
|
@ -690,7 +692,7 @@ export function ProductInnovationPage() {
|
|||
</div>
|
||||
<div className="flex items-center justify-center flex-col p-1">
|
||||
<div
|
||||
className="h-8 bg-gray-600 rounded animate-pulse"
|
||||
className="h-8 bg-gray-600 rounded animate-pulse mb-1"
|
||||
style={{ width: "40%" }}
|
||||
/>
|
||||
<div
|
||||
|
|
@ -702,55 +704,54 @@ export function ProductInnovationPage() {
|
|||
</CardContent>
|
||||
</Card>
|
||||
))
|
||||
: Object.entries(stateCard).map(([key, card], index) => (
|
||||
<Card
|
||||
key={card.id}
|
||||
className={`bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm border-gray-700/50 ${index !== 0 ? "row-start-2 " : "col-span-2"} `}
|
||||
>
|
||||
<CardContent className="p-2 h-full">
|
||||
<div className="grid grid-cols-2 justify-between gap-2 h-full">
|
||||
<div className="flex justify-between rows-start-1 col-span-2 items-center border-b-2 mx-4 border-gray-500/20">
|
||||
<h3 className="text-lg text-white font-persian py-2">
|
||||
{card.title}
|
||||
</h3>
|
||||
<div
|
||||
className={`p-3 gird placeitems-center rounded-full w-fit `}
|
||||
>
|
||||
) : (
|
||||
<>
|
||||
{/* First card (Metric/Matrix style) - span two columns */}
|
||||
<div className="col-span-2">
|
||||
<MetricCard
|
||||
title={stateCard.revenueNewProducts.title}
|
||||
value={stateCard.revenueNewProducts.value}
|
||||
percentValue={stateCard.revenueNewProducts.percent}
|
||||
valueLabel={stateCard.revenueNewProducts.description}
|
||||
percentLabel={stateCard.revenueNewProducts.descriptionPercent}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className={`flex items-center row-start-2 justify-center flex-col row-start-2 p-1 my-auto ${card?.percent ? "col-span-1 col-start-1" : "col-span-2"}`}>
|
||||
<p
|
||||
className={`text-3xl font-bold ${card.color} mb-1`}
|
||||
>
|
||||
{card.value}
|
||||
|
||||
</p>
|
||||
<p className="text-sm text-gray-300 font-persian">
|
||||
{card.description}
|
||||
</p>
|
||||
{/* Second card */}
|
||||
<div>
|
||||
<BaseCard title={stateCard.newProductExports.title} className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm border-gray-700/50">
|
||||
<div className="flex items-center justify-center flex-col">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="text-center">
|
||||
<p className="text-3xl font-bold mb-1 text-pr-green">{stateCard.newProductExports.value}</p>
|
||||
<div className="text-xs text-gray-400 font-persian">{stateCard.newProductExports.description}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</BaseCard>
|
||||
</div>
|
||||
{card?.percent && <span className="text-gray-600 row-start-2 col-span-2 self-center col-start-2 font-thin text-5xl">/</span>}
|
||||
{card?.percent && <div className="flex col-span-1 items-center row-start-2 my-auto col-start-2 justify-center flex-col p-1 my-auto">
|
||||
<p
|
||||
className={`text-3xl font-bold ${card.color} mb-1`}
|
||||
>
|
||||
{card?.percent}
|
||||
|
||||
</p>
|
||||
<p className="text-sm text-gray-300 font-persian">
|
||||
{card.descriptionPercent}
|
||||
</p>
|
||||
</div>}
|
||||
{/* Third card - basic BaseCard */}
|
||||
<div>
|
||||
<BaseCard title={stateCard.impactOnImports.title} className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] backdrop-blur-sm border-gray-700/50">
|
||||
<div className="flex items-center justify-center flex-col">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="text-center">
|
||||
<p className="text-3xl font-bold mb-1 text-pr-red">{stateCard.impactOnImports.value}</p>
|
||||
<div className="text-xs text-gray-400 font-persian">{stateCard.impactOnImports.description}</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</BaseCard>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Funnel Chart */}
|
||||
<Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] h-full backdrop-blur-sm rounded-2xl w-full overflow-hidden">
|
||||
<CardContent className="p-6">
|
||||
<CardContent className="px-0 py-4">
|
||||
<FunnelChart
|
||||
title="قيف فرآیند پروژه ها"
|
||||
data={[
|
||||
|
|
@ -795,7 +796,7 @@ export function ProductInnovationPage() {
|
|||
{columns.map((column) => (
|
||||
<TableHead
|
||||
key={column.key}
|
||||
className="text-center font-persian whitespace-nowrap text-gray-200 font-medium sticky top-0 z-20 bg-[#3F415A]"
|
||||
className="text-center font-persian whitespace-nowrap text-white font-medium sticky top-0 z-20 bg-pr-gray text-sm font-semibold"
|
||||
style={{ width: column.width }}
|
||||
>
|
||||
{column.sortable ? (
|
||||
|
|
@ -891,10 +892,10 @@ export function ProductInnovationPage() {
|
|||
</CardContent>
|
||||
|
||||
{/* Footer */}
|
||||
<div className="p-2 px-4 bg-[#3F415A]">
|
||||
<div className="p-2 px-4 bg-pr-gray">
|
||||
<div className="flex gap-4 text-sm text-gray-300 font-persian justify-between sm:flex-col xl:flex-row">
|
||||
<div className="text-center gap-2 items-center xl:w-1/3 pr-36 sm:w-full">
|
||||
<div className="text-base text-gray-401">
|
||||
<div className="text-sm font-semibold text-white">
|
||||
کل پروژه ها :{formatNumber(stats?.count_innovation_construction_inside_projects)}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -907,8 +908,8 @@ export function ProductInnovationPage() {
|
|||
<span className="block w-7 h-2.5 bg-pink-400 rounded-tr-xl rounded-br-xl"></span>
|
||||
</div>
|
||||
<div className="flex justify-center items-center gap-2">
|
||||
<div className="text-base text-gray-400">میانگین :</div>
|
||||
<div className="font-bold">
|
||||
<div className="text-bold text-sm text-white">میانگین :</div>
|
||||
<div className="font-bold text-sm text-white">
|
||||
{formatNumber(
|
||||
((stats.average_project_score ?? 0) as number).toFixed?.(1) ?? 0
|
||||
)}
|
||||
|
|
@ -924,7 +925,7 @@ export function ProductInnovationPage() {
|
|||
<Dialog open={detailsDialogOpen} onOpenChange={setDetailsDialogOpen}>
|
||||
<DialogContent className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] max-w-7xl max-h-[95vh] overflow-y-auto">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="text-white mr-4 border-b-2 border-gray-600 pb-2 font-persian text-right">
|
||||
<DialogTitle className="text-white mr-4 border-b-2 border-gray-600 pb-2 text-sm font-semibold font-persian text-right">
|
||||
شرح پروژه
|
||||
</DialogTitle>
|
||||
</DialogHeader>
|
||||
|
|
@ -934,17 +935,17 @@ export function ProductInnovationPage() {
|
|||
<div className="space-y-4">
|
||||
{/* Stats Cards */}
|
||||
<div className="space-y-4">
|
||||
<h3 className="font-bold text-lg">{selectedProjectDetails?.title}</h3>
|
||||
<h3 className="font-bold text-base">{selectedProjectDetails?.title}</h3>
|
||||
<p className="py-2">{selectedProjectDetails?.project_description}</p>
|
||||
</div>
|
||||
<Timeline />
|
||||
|
||||
{/* Technical Knowledge */}
|
||||
<div className=" rounded-lg py-2 mb-0">
|
||||
<h3 className="text-sm text-gray-400 mb-2">دانش فنی محصول جدید</h3>
|
||||
<h3 className="text-sm text-white font-semibold mb-2">دانش فنی محصول جدید</h3>
|
||||
<div className="flex gap-4 items-center">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-sm text-white">توسعه درونزا</span>
|
||||
<span className="text-sm text-white font-light">توسعه درونزا</span>
|
||||
|
||||
<Checkbox
|
||||
checked={selectedProjectDetails?.developed_technology_type === "توسعه درونزا"}
|
||||
|
|
@ -953,7 +954,7 @@ export function ProductInnovationPage() {
|
|||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-sm text-white">همکاری فناورانه</span>
|
||||
<span className="text-sm text-white font-light">همکاری فناورانه</span>
|
||||
|
||||
<Checkbox
|
||||
checked={selectedProjectDetails?.developed_technology_type === "همکاری فناوری"}
|
||||
|
|
@ -962,7 +963,7 @@ export function ProductInnovationPage() {
|
|||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-sm text-white">سایر</span>
|
||||
<span className="text-sm text-white font-light">سایر</span>
|
||||
<Checkbox
|
||||
checked={selectedProjectDetails?.developed_technology_type === "سایر"}
|
||||
className="data-[state=checked]:bg-emerald-600 data-[state=checked]:border-emerald-600"
|
||||
|
|
@ -973,7 +974,7 @@ export function ProductInnovationPage() {
|
|||
|
||||
{/* Standards */}
|
||||
<div className="rounded-lg py-4">
|
||||
<h3 className="text-sm text-gray-400 mb-4">
|
||||
<h3 className="text-sm text-white font-semibold mb-4">
|
||||
استانداردهای ملی و بینالمللی اخذ شده
|
||||
</h3>
|
||||
|
||||
|
|
@ -985,7 +986,7 @@ export function ProductInnovationPage() {
|
|||
).map((standard, index) => (
|
||||
<div key={index} className="flex items-center gap-2">
|
||||
<div className="w-2 h-2 bg-emerald-500 rounded-full"></div>
|
||||
<span className="text-sm text-white">{standard}</span>
|
||||
<span className="text-sm text-white font-light">{standard}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
|
@ -997,21 +998,21 @@ export function ProductInnovationPage() {
|
|||
</div>
|
||||
|
||||
{/* Knowledge-based Certificate Button */}
|
||||
<div className="justify-self-centerr py-1 mx-auto">
|
||||
<div className="justify-self-centerr grid py-1 mx-auto">
|
||||
{selectedProjectDetails?.knowledge_based_certificate_obtained === "خیر" ? (
|
||||
<div className=" border border-red-600 rounded-lg p-2 text-center">
|
||||
<button className="text-red-400 font-medium">
|
||||
<div className=" border border-pr-red mx-auto rounded-lg p-2 text-center">
|
||||
<button className="text-pr-red font-bold text-sm">
|
||||
گواهی دانشبنیان ندارد
|
||||
</button>
|
||||
</div>
|
||||
) : (
|
||||
<Card className="justify-self-center border-emerald-600 bg-transparent py-0">
|
||||
<Card className="justify-self-center border-pr-green bg-transparent py-0">
|
||||
<CardContent className="p-2 text-center">
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
variant="default"
|
||||
className=" text-emerald-400 hover:bg-transparent cursor-pointer bg-transparent"
|
||||
className=" text-pr-green font-bold text-sm hover:bg-transparent cursor-pointer bg-transparent"
|
||||
>
|
||||
مشاهده اطلاعات گواهی دانشبنیان
|
||||
</Button>
|
||||
|
|
@ -1070,103 +1071,37 @@ export function ProductInnovationPage() {
|
|||
</div>
|
||||
) : (
|
||||
<div className="lg:col-span-2 border-r-2 flex flex-col gap-2 pr-4 pb-2 border-r-[#5F6284]/50">
|
||||
{/* Project Description */}
|
||||
<div className=" rounded-lg pt-4 flex w-full gap-2">
|
||||
<Card
|
||||
className="bg-[linear-gradient(to_bottom_left,#464861,45%,#111628)] flex-1 backdrop-blur-sm border-gray-700/50 col-span-2"
|
||||
>
|
||||
<CardContent className="p-2 h-full">
|
||||
<div className="grid grid-cols-2 justify-between gap-2 h-full">
|
||||
<div className="flex justify-between rows-start-1 col-span-2 items-center border-b-2 mx-4 border-gray-500/20">
|
||||
<h3 className="text-lg text-white font-persian py-2">
|
||||
میزان صادارت محصول جدید
|
||||
</h3>
|
||||
|
||||
</div>
|
||||
|
||||
<div className="flex col-span-1 items-center row-start-2 my-auto col-start-1 justify-center flex-col p-1 my-auto">
|
||||
<p
|
||||
className={`text-2xl font-bold mb-1`}
|
||||
>
|
||||
{formatNumber(Math.round(popupStats?.new_products_export > 0 ? popupStats?.new_products_export : 0)) || formatNumber(0)}
|
||||
</p>
|
||||
<p className="text-xs font-thin text-gray-300 font-persian">
|
||||
میلیون ریال
|
||||
</p>
|
||||
</div>
|
||||
<span className="text-gray-600 row-start-2 self-center col-start-2 font-thin text-5xl">/</span>
|
||||
<div className="flex col-span-1 items-center row-start-2 my-auto col-start-2 justify-center flex-col p-1 my-auto">
|
||||
<p
|
||||
className={`text-2xl font-bold mb-1`}
|
||||
>
|
||||
{formatNumber(Math.round(popupStats?.new_products_export_percent > 0 ? popupStats?.new_products_export_percent : 0)) || formatNumber(0)}%
|
||||
</p>
|
||||
<p className="text-xs font-thin text-gray-300 font-persian">
|
||||
درصد به کل صادرات
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card
|
||||
className="bg-[linear-gradient(to_bottom_left,#464861,45%,#111628)] flex-1 backdrop-blur-sm border-gray-700/50 col-span-2"
|
||||
>
|
||||
<CardContent className="p-2 h-full">
|
||||
<div className="grid grid-cols-2 justify-between gap-2 h-full">
|
||||
<div className="flex justify-between rows-start-1 col-span-2 items-center border-b-2 mx-4 border-gray-500/20">
|
||||
<h3 className="text-lg text-white font-persian py-2">
|
||||
تاثیر در واردات
|
||||
</h3>
|
||||
|
||||
</div>
|
||||
|
||||
<div className="flex col-span-1 items-center row-start-2 my-auto col-start-1 justify-center flex-col p-1 my-auto">
|
||||
<p
|
||||
className={`text-2xl font-bold mb-1`}
|
||||
>
|
||||
{formatNumber(Math.round(popupStats?.import_impact > 0 ? popupStats?.import_impact : 0)) || formatNumber(0)}
|
||||
</p>
|
||||
<p className="text-xs font-thin text-gray-300 font-persian">
|
||||
میلیون ریال
|
||||
</p>
|
||||
</div>
|
||||
<span className="text-gray-600 row-start-2 self-center col-start-2 font-thin text-5xl">/</span>
|
||||
<div className="flex col-span-1 items-center row-start-2 my-auto col-start-2 justify-center flex-col p-1 my-auto">
|
||||
<p
|
||||
className={`text-2xl font-bold mb-1`}
|
||||
>
|
||||
{formatNumber(Math.round(popupStats?.import_impact_percent > 0 ? popupStats?.import_impact_percent : 0)) || formatNumber(0)}%
|
||||
</p>
|
||||
<p className="text-xs font-thin text-gray-300 font-persian">
|
||||
درصد صرفه جویی
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
|
||||
{/* Project Description - two MetricCards side by side */}
|
||||
<div className="rounded-lg pt-4 grid grid-cols-2 gap-4 w-full">
|
||||
<MetricCard
|
||||
title="میزان صادارت محصول جدید"
|
||||
value={Math.round(popupStats?.new_products_export > 0 ? popupStats?.new_products_export : 0)}
|
||||
percentValue={Math.round(popupStats?.new_products_export_percent > 0 ? popupStats?.new_products_export_percent : 0)}
|
||||
valueLabel="میلیون ریال"
|
||||
percentLabel="درصد به کل صادرات"
|
||||
/>
|
||||
|
||||
<MetricCard
|
||||
title="تاثیر در واردات"
|
||||
value={Math.round(popupStats?.import_impact > 0 ? popupStats?.import_impact : 0)}
|
||||
percentValue={Math.round(popupStats?.import_impact_percent > 0 ? popupStats?.import_impact_percent : 0)}
|
||||
valueLabel="میلیون ریال"
|
||||
percentLabel="درصد صرفه جویی"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Export Revenue Bar Chart */}
|
||||
<div className="bg-[linear-gradient(to_bottom_left,#464861,45%,#111628)] rounded-lg px-6 py-4">
|
||||
<h3 className="text-lg font-semibold text-white">ظرفیت صادر شده</h3>
|
||||
<h3 className="text-sm font-semibold text-white">ظرفیت صادر شده</h3>
|
||||
<div className="h-60">
|
||||
{popupLoading ? (
|
||||
<div className="flex items-center justify-center h-full">
|
||||
<div className="animate-pulse my-auto text-gray-400">در حال بارگذاری...</div>
|
||||
</div>
|
||||
) : exportChartData.length > 0 ? (
|
||||
<ResponsiveContainer width="100%" height="100%" >
|
||||
<BarChart className="aspect-auto w-full"
|
||||
{exportChartData.length > 0 ? (
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<BarChart
|
||||
className="aspect-auto w-full"
|
||||
data={sortedBarData}
|
||||
barGap={15}
|
||||
barSize={30}
|
||||
margin={{
|
||||
top : 18
|
||||
}}
|
||||
margin={{ top: 18 }}
|
||||
>
|
||||
<CartesianGrid vertical={false} stroke="#475569" />
|
||||
<XAxis
|
||||
|
|
@ -1176,126 +1111,44 @@ export function ProductInnovationPage() {
|
|||
stroke="#C3C3C3"
|
||||
tickMargin={8}
|
||||
tickFormatter={(value: string) => `${value.split(" ")[0]} ${formatNumber(value.split(" ")[1]).replaceAll('٬','')}`}
|
||||
fontSize={11}
|
||||
/>
|
||||
<YAxis
|
||||
tickLine={false}
|
||||
axisLine={false}
|
||||
stroke="#9CA3AF"
|
||||
fontSize={11} tick={{ dx: -50 }} tickFormatter={(value: number) => `${formatNumber(value)} میلیون`}/>
|
||||
<Bar
|
||||
dataKey="value"
|
||||
fill="#10B981"
|
||||
radius={10}
|
||||
>
|
||||
<LabelList
|
||||
formatter={(value : number) => `${formatNumber(value)}`}
|
||||
position="top"
|
||||
offset={15}
|
||||
fill="F9FAFB"
|
||||
className="fill-foreground"
|
||||
fontSize={16}
|
||||
/>
|
||||
<YAxis tickLine={false} axisLine={false} stroke="#9CA3AF" fontSize={11} tick={{ dx: -50 }} tickFormatter={(value: number) => `${formatNumber(value)} میلیون`} />
|
||||
<Bar dataKey="value" fill="#10B981" radius={10}>
|
||||
<LabelList formatter={(value: number) => `${formatNumber(value)}`} position="top" offset={15} fill="F9FAFB" className="fill-foreground" fontSize={16} />
|
||||
</Bar>
|
||||
|
||||
</BarChart>
|
||||
</ResponsiveContainer>
|
||||
) : (
|
||||
<div className="flex items-center justify-center h-full text-gray-400">
|
||||
دادهای برای نمایش وجود ندارد
|
||||
</div>
|
||||
<div className="flex items-center justify-center h-full text-gray-400">دادهای برای نمایش وجود ندارد</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Export Revenue Line Chart */}
|
||||
<div className="bg-[linear-gradient(to_bottom_left,#464861,45%,#111628)] rounded-lg px-6 py-4">
|
||||
<h3 className="text-lg font-semibold text-white">ظرفیت صادر شده</h3>
|
||||
<h3 className="text-sm font-semibold text-white">ظرفیت صادر شده</h3>
|
||||
<div className="h-60">
|
||||
{popupLoading ? (
|
||||
<div className="flex items-center justify-center ">
|
||||
<div className="animate-pulse my-auto text-gray-400">در حال بارگذاری...</div>
|
||||
</div>
|
||||
) : allExportData.length > 0 ? (
|
||||
{allExportData.length > 0 ? (
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<LineChart
|
||||
accessibilityLayer
|
||||
className="aspect-auto w-full "
|
||||
data={transformDataForLineChart(allExportData)}
|
||||
margin={{ top: 20, right: 30, left: 10, bottom: 50 }}
|
||||
>
|
||||
<LineChart className="aspect-auto w-full" data={transformDataForLineChart(allExportData)} margin={{ top: 20, right: 30, left: 10, bottom: 50 }}>
|
||||
<CartesianGrid vertical={false} stroke="#374151" />
|
||||
<XAxis
|
||||
dataKey="season"
|
||||
stroke="#9CA3AF"
|
||||
fontSize={11}
|
||||
tick={({ x, y, payload }) => (
|
||||
<XAxis dataKey="season" stroke="#9CA3AF" fontSize={11} tick={({ x, y, payload }) => (
|
||||
<g transform={`translate(${x},${y + 10})`}>
|
||||
<text
|
||||
x={-40}
|
||||
y={15}
|
||||
dy={0}
|
||||
textAnchor="end"
|
||||
fill="#9CA3AF"
|
||||
fontSize={11}
|
||||
transform="rotate(-45)"
|
||||
>
|
||||
{payload.value}
|
||||
</text>
|
||||
<text x={-40} y={15} dy={0} textAnchor="end" fill="#9CA3AF" fontSize={11} transform="rotate(-45)">{(payload as any).value}</text>
|
||||
</g>
|
||||
)}
|
||||
/>
|
||||
<YAxis
|
||||
tickLine={false}
|
||||
axisLine={false}
|
||||
stroke="#9CA3AF"
|
||||
fontSize={11}
|
||||
tick={{ dx: -50 }}
|
||||
tickFormatter={(value) => `${formatNumber(value)} میلیون`} // 👈 اضافه کردن M کنار اعداد
|
||||
/>
|
||||
|
||||
<Tooltip
|
||||
formatter={(value : number) => `${formatNumber(value)} میلیون`}
|
||||
contentStyle={{
|
||||
backgroundColor: "#1F2937",
|
||||
border: "1px solid #374151",
|
||||
borderRadius: "6px",
|
||||
padding: "6px 10px",
|
||||
fontSize: "11px",
|
||||
color: "#F9FAFB",
|
||||
}}
|
||||
/>
|
||||
<Legend
|
||||
layout="vertical"
|
||||
verticalAlign="middle"
|
||||
align="right"
|
||||
iconType={"plainline"}display={"flex !important"}
|
||||
className="!flex"
|
||||
wrapperStyle={{ fontSize: 11 , paddingLeft : 12 , display : "flex !important" , gap : 10} }
|
||||
/>
|
||||
|
||||
{[...new Set(allExportData.map((item) => item.product_title))]
|
||||
.slice(0, 5)
|
||||
.map((product, index) => {
|
||||
)} />
|
||||
<YAxis tickLine={false} axisLine={false} stroke="#9CA3AF" fontSize={11} tick={{ dx: -50 }} tickFormatter={(value) => `${formatNumber(value)} میلیون`} />
|
||||
<Tooltip formatter={(value: number) => `${formatNumber(value)} میلیون`} contentStyle={{ backgroundColor: "#1F2937", border: "1px solid #374151", borderRadius: "6px", padding: "6px 10px", fontSize: "11px", color: "#F9FAFB" }} />
|
||||
<Legend layout="vertical" verticalAlign="middle" align="right" iconType={"plainline"} className="!flex" wrapperStyle={{ fontSize: 11, paddingLeft: 12, gap: 10 }} />
|
||||
{[...new Set(allExportData.map((item) => item.product_title))].slice(0, 5).map((product, index) => {
|
||||
const colors = ["#10B981", "#EF4444", "#3B82F6", "#F59E0B", "#8B5CF6"];
|
||||
return (
|
||||
<Line
|
||||
key={product.product_title}
|
||||
type="linear"
|
||||
dot={false}
|
||||
activeDot={{ r: 5 }}
|
||||
dataKey={product}
|
||||
stroke={colors[index % colors.length]}
|
||||
strokeWidth={2}
|
||||
/>
|
||||
);
|
||||
return <Line key={product} type="linear" dot={false} activeDot={{ r: 5 }} dataKey={product} stroke={colors[index % colors.length]} strokeWidth={2} />;
|
||||
})}
|
||||
</LineChart>
|
||||
</ResponsiveContainer>
|
||||
|
||||
) : (
|
||||
<div className="flex items-center justify-center h-full text-gray-400">
|
||||
دادهای برای نمایش وجود ندارد
|
||||
</div>
|
||||
<div className="flex items-center justify-center h-full text-gray-400">دادهای برای نمایش وجود ندارد</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -24,18 +24,18 @@ export function FunnelChart({ data, title, className = "" }: FunnelChartProps) {
|
|||
return (
|
||||
<div className={`w-full ${className}`}>
|
||||
{title && (
|
||||
<h3 className="text-lg font-semibold text-white mb-4 py-2 text-right border-b-2 border-gray-400/20">
|
||||
<h3 className="text-sm px-4 font-semibold text-white mb-4 py-2 text-right border-b-2 border-gray-400/20">
|
||||
{title}
|
||||
</h3>
|
||||
)}
|
||||
|
||||
<div className="flex flex-col items-center gap-2 space-y-2">
|
||||
<div className="flex px-4 flex-col items-center gap-2 space-y-2">
|
||||
{/* Start Process Line */}
|
||||
<div className="flex items-center w-full gap-10 mt-6">
|
||||
<div className="text-lg text-gray-600 min-w-[max-content]">ابتدا فرآیند</div>
|
||||
<div className="flex items-center w-full gap-10 mt-6 px-4">
|
||||
<div className="text-sm font-normal text-[#5F6284] min-w-[max-content]">ابتدا فرآیند</div>
|
||||
<div className="flex items-center w-full gap-4">
|
||||
<div className="w-full h-0.5 bg-gray-600 relative">
|
||||
<div className="text-2xl text-white absolute left-1/2 -translate-x-1/2 top-[-1rem] -translate-y-1/2">۱۰۰%</div>
|
||||
<div className="text-base text-white font-semibold absolute left-1/2 -translate-x-1/2 top-[-1rem] -translate-y-1/2">۱۰۰%</div>
|
||||
<div className="absolute -top-1 left-0 w-1 h-3 bg-gray-600"></div>
|
||||
<div className="absolute -top-1 right-0 w-1 h-3 bg-gray-600"></div>
|
||||
</div>
|
||||
|
|
@ -50,7 +50,7 @@ export function FunnelChart({ data, title, className = "" }: FunnelChartProps) {
|
|||
|
||||
return (
|
||||
<div key={index} className="grid grid-cols-[6rem_1fr] gap-2 w-full">
|
||||
<div className="text-lg text-white cols-start-1 justify-self-start font-thin min-w-[max-content] text-center">
|
||||
<div className="text-sm font-light text-white cols-start-1 justify-self-start font-thin min-w-[max-content] text-center">
|
||||
{item.label}
|
||||
</div>
|
||||
<div className="flex items-center gap-10 w-full cols-start-2 flex items-center justify-center w-full">
|
||||
|
|
@ -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}%` }}
|
||||
>
|
||||
<span className="text-[#3F415A] font-semibold">
|
||||
<span className="text-pr-gray text-base font-semibold">
|
||||
{item.value.toLocaleString('fa-IR')}
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -73,15 +73,15 @@ export function FunnelChart({ data, title, className = "" }: FunnelChartProps) {
|
|||
</div>
|
||||
|
||||
{/* End Process Line */}
|
||||
<div className="flex items-center w-full gap-10">
|
||||
<div className="text-lg text-gray-600 min-w-[max-content]">انتها فرآیند</div>
|
||||
<div className="flex items-center w-full gap-10 px-4">
|
||||
<div className="text-sm text-[#5F6284] min-w-[max-content]">انتها فرآیند</div>
|
||||
<div className="flex items-center w-full gap-4">
|
||||
{(() => {
|
||||
const lastValue = data[data.length - 1]?.value ?? 0;
|
||||
const percent = toPercent(lastValue);
|
||||
return (
|
||||
<div style={{ width: `${percent}%` }} className={`mx-auto h-0.5 bg-gray-600 relative ${percent === 0 ? "hidden" : ""}`}>
|
||||
<div className="text-2xl text-white absolute left-1/2 -translate-x-1/2 bottom-[-2.5rem] -translate-y-1">{formatNumber(percent)}%</div>
|
||||
<div className="text-base font-semibold text-white absolute left-1/2 -translate-x-1/2 bottom-[-2.5rem] -translate-y-1">{formatNumber(percent)}%</div>
|
||||
<div className="absolute -top-1 left-0 w-1 h-3 bg-gray-600"></div>
|
||||
<div className="absolute -top-1 right-0 w-1 h-3 bg-gray-600"></div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user