fix the customChartBar in dashboard and process-innvation, also fix the style in dashboard and ecosystem's popup
This commit is contained in:
parent
1a0cf20319
commit
585e66570d
|
|
@ -130,18 +130,18 @@ export function DashboardHome() {
|
|||
let incCapacityTotal = 0;
|
||||
const chartRows = rows.map((r) => {
|
||||
const rel = r?.related_company ?? "-";
|
||||
const preFee = Number(r?.pre_innovation_fee_sum ?? 0) > 0 ? r?.pre_innovation_fee_sum : 0;
|
||||
const costRed = Number(r?.innovation_cost_reduction_sum ?? 0) > 0 ? r?.innovation_cost_reduction_sum : 0;
|
||||
const preCap = Number(r?.pre_project_production_capacity_sum ?? 0) > 0 ? r?.pre_project_production_capacity_sum : 0;
|
||||
const incCap = Number(r?.increased_capacity_after_innovation_sum ?? 0) > 0 ? r?.increased_capacity_after_innovation_sum : 0;
|
||||
const preInc = Number(r?.pre_project_income_sum ?? 0) > 0 ? r?.pre_project_income_sum : 0;
|
||||
const incInc = Number(r?.increased_income_after_innovation_sum ?? 0) > 0 ? r?.increased_income_after_innovation_sum : 0;
|
||||
const preFee = Number(r?.pre_innovation_fee_sum ?? 0) >= 0 ? r?.pre_innovation_fee_sum : 0;
|
||||
const costRed = Number(r?.innovation_cost_reduction_sum ?? 0) >= 0 ? r?.innovation_cost_reduction_sum : 0;
|
||||
const preCap = Number(r?.pre_project_production_capacity_sum ?? 0) >= 0 ? r?.pre_project_production_capacity_sum : 0;
|
||||
const incCap = Number(r?.increased_capacity_after_innovation_sum ?? 0) >= 0 ? r?.increased_capacity_after_innovation_sum : 0;
|
||||
const preInc = Number(r?.pre_project_income_sum ?? 0) >= 0 ? r?.pre_project_income_sum : 0;
|
||||
const incInc = Number(r?.increased_income_after_innovation_sum ?? 0) >= 0 ? r?.increased_income_after_innovation_sum : 0;
|
||||
|
||||
incCapacityTotal += incCap;
|
||||
|
||||
const capacityPct = preCap > 0 ? (incCap / preCap) * 100 : 0;
|
||||
const revenuePct = preInc > 0 ? (incInc / preInc) * 100 : 0;
|
||||
const costPct = preFee > 0 ? (costRed / preFee) * 100 : 0;
|
||||
const capacityPct = preCap >= 0 ? (incCap / preCap) * 100 : 0;
|
||||
const revenuePct = preInc >= 0 ? (incInc / preInc) * 100 : 0;
|
||||
const costPct = preFee >= 0 ? (costRed / preFee) * 100 : 0;
|
||||
return {
|
||||
category: rel,
|
||||
capacity: isFinite(capacityPct) ? capacityPct : 0,
|
||||
|
|
@ -178,7 +178,7 @@ export function DashboardHome() {
|
|||
dashboardData.topData.ongoing_innovation_technology_ideas || "0",
|
||||
);
|
||||
const percentage =
|
||||
registered > 0 ? Math.round((ongoing / registered) * 100) : 0;
|
||||
registered > 0 ? (ongoing / registered) * 100 : 0;
|
||||
|
||||
return [
|
||||
{ browser: "safari", visitors: percentage, fill: "var(--color-safari)" },
|
||||
|
|
@ -461,7 +461,7 @@ export function DashboardHome() {
|
|||
<MetricCard
|
||||
title="افزایش درآمد مبتنی بر فناوری و نوآوری"
|
||||
value={dashboardData.topData?.technology_innovation_based_revenue_growth || "0"}
|
||||
percentValue={Math.round(dashboardData.topData?.technology_innovation_based_revenue_growth_percent) || "0"}
|
||||
percentValue={dashboardData.topData?.technology_innovation_based_revenue_growth_percent}
|
||||
percentLabel="درصد به کل درآمد"
|
||||
/>
|
||||
|
||||
|
|
@ -469,7 +469,7 @@ export function DashboardHome() {
|
|||
<MetricCard
|
||||
title="کاهش هزینه ها مبتنی بر فناوری و نوآوری"
|
||||
value={Math.round(parseFloat(dashboardData.topData?.technology_innovation_based_cost_reduction?.replace(/,/g, "") || "0") / 1000000)}
|
||||
percentValue={Math.round(dashboardData.topData?.technology_innovation_based_cost_reduction_percent) || "0"}
|
||||
percentValue={dashboardData.topData?.technology_innovation_based_cost_reduction_percent || "0"}
|
||||
percentLabel="درصد به کل هزینه"
|
||||
/>
|
||||
|
||||
|
|
@ -646,17 +646,10 @@ export function DashboardHome() {
|
|||
<CardTitle className="text-white text-sm min-w-[100px]">
|
||||
شدت فناوری
|
||||
</CardTitle>
|
||||
<p className="text-base text-left">
|
||||
%
|
||||
{formatNumber(
|
||||
Math.round(
|
||||
dashboardData.leftData?.technology_intensity || 0,
|
||||
),
|
||||
)}
|
||||
</p>
|
||||
|
||||
<Progress
|
||||
value={parseFloat(
|
||||
dashboardData.leftData?.technology_intensity || "0",
|
||||
dashboardData.leftData?.technology_intensity,
|
||||
)}
|
||||
className="h-4 flex-1"
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -260,7 +260,6 @@ export function ProcessInnovationPage() {
|
|||
Pagination: { PageNumber: pageToFetch, PageSize: pageSize },
|
||||
});
|
||||
|
||||
console.log(JSON.parse(response.data));
|
||||
if (response.state === 0) {
|
||||
const dataString = response.data;
|
||||
if (dataString && typeof dataString === "string") {
|
||||
|
|
@ -656,6 +655,12 @@ export function ProcessInnovationPage() {
|
|||
</div>
|
||||
|
||||
{/* Process Impacts Chart */}
|
||||
{/* نمودار با الگوریتم Nice Numbers:
|
||||
مثلاً اگر دادهها [10, 35, 63, 18] باشند:
|
||||
- حداکثر: 63، با حاشیه 5% = 66.15
|
||||
- Nice Max: 75 (گرد و خوانا)
|
||||
- Ticks: [0, 20, 40, 60, 75]
|
||||
این باعث میشود نمودار زیباتر و خواناتر باشد */}
|
||||
<BaseCard className="rounded-2xl w-full overflow-hidden">
|
||||
<CustomBarChart
|
||||
title="تاثیرات فرآیندی به صورت درصد مقایسه ای"
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ interface ProjectData {
|
|||
project_id: string;
|
||||
title: string;
|
||||
project_status: string;
|
||||
current_status?: string;
|
||||
project_rating: string;
|
||||
project_description: string;
|
||||
developed_technology_type: string;
|
||||
|
|
@ -94,6 +95,7 @@ interface ProductInnovationData {
|
|||
title: string;
|
||||
project_status: projectStatus;
|
||||
project_rating: string;
|
||||
current_status?: string;
|
||||
project_description: string;
|
||||
developed_technology_type: string;
|
||||
obtained_standard_title: string;
|
||||
|
|
@ -138,10 +140,14 @@ const columns = [
|
|||
];
|
||||
|
||||
|
||||
export default function Timeline() {
|
||||
const stages = ["تجاری سازی", "توسعه", "تحلیل بازار", "ثبت ایده"];
|
||||
const currentStage = 1; // index of current stage
|
||||
|
||||
export default function Timeline( valueTimeLine : string) {
|
||||
const stages = ["تجاری سازی", "توسعه", "تحلیل بازار", "ثبت ایده"];
|
||||
const currentStage = stages?.toReversed()?.findIndex((x : string) => x == valueTimeLine)
|
||||
const per = () => {
|
||||
const main = stages?.findIndex((x) => x == "ثبت ایده")
|
||||
console.log( 'yay ' , 25 * main + 12.5);
|
||||
return 25 * main + 12.5
|
||||
}
|
||||
return (
|
||||
<div className="w-full p-4">
|
||||
{/* Year labels */}
|
||||
|
|
@ -151,7 +157,6 @@ export default function Timeline() {
|
|||
<span>۱۴۰۵</span>
|
||||
<span>۱۴۰۴</span>
|
||||
</div>
|
||||
|
||||
{/* Timeline bar */}
|
||||
<div className="relative rounded-lg flex mb-4 items-center">
|
||||
{stages.map((stage, index) => (
|
||||
|
|
@ -171,15 +176,17 @@ export default function Timeline() {
|
|||
))}
|
||||
|
||||
{/* Vertical line showing current position */}
|
||||
<div
|
||||
className="absolute left-[37%] top-0 h-[150%] bottom-0 w-[2px] bg-white rounded-full"
|
||||
{ valueTimeLine?.length > 0 && ( <> <div
|
||||
className={`absolute top-0 h-[150%] bottom-0 w-[2px] bg-white rounded-full`}
|
||||
style={{ left: `${(currentStage + 0.5) * (100 / stages.length)}%` }}
|
||||
/>
|
||||
<div
|
||||
className="absolute top-15 h-[max-content] translate-x-[-50%] text-xs text-gray-300 border-gray-400 rounded-md border px-2 bottom-0"
|
||||
style={{ left: `${(currentStage + 0.5) * (100 / stages.length)}%` }}
|
||||
>وضعیت فعلی</div>
|
||||
</div>
|
||||
</> ) }
|
||||
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -343,6 +350,7 @@ export function ProductInnovationPage() {
|
|||
"project_no",
|
||||
"title",
|
||||
"project_status",
|
||||
"current_status",
|
||||
"project_rating",
|
||||
"project_description",
|
||||
"developed_technology_type",
|
||||
|
|
@ -350,7 +358,7 @@ export function ProductInnovationPage() {
|
|||
"knowledge_based_certificate_obtained",
|
||||
"knowledge_based_certificate_number",
|
||||
"certificate_obtain_date",
|
||||
"issuing_authority",
|
||||
"issuing_authority"
|
||||
],
|
||||
Sorts: [["start_date", "asc"]],
|
||||
Conditions: [["type_of_innovation", "=", "نوآوری در محصول"]],
|
||||
|
|
@ -458,8 +466,8 @@ export function ProductInnovationPage() {
|
|||
...prev,
|
||||
revenueNewProducts: {
|
||||
...prev.revenueNewProducts,
|
||||
value: formatNumber(normalized.new_products_revenue_share),
|
||||
percent: formatNumber(normalized.new_products_revenue_share_percent),
|
||||
value: formatNumber(normalized?.new_products_revenue_share),
|
||||
percent: formatNumber(normalized?.new_products_revenue_share_percent),
|
||||
},
|
||||
impactOnImports: {
|
||||
...prev.impactOnImports,
|
||||
|
|
@ -708,8 +716,8 @@ export function ProductInnovationPage() {
|
|||
<div className="col-span-2">
|
||||
<MetricCard
|
||||
title={stateCard.revenueNewProducts.title}
|
||||
value={stateCard.revenueNewProducts.value}
|
||||
percentValue={stateCard.revenueNewProducts.percent}
|
||||
value={formatNumber(stateCard.revenueNewProducts.value)}
|
||||
percentValue={formatNumber(stateCard.revenueNewProducts.percent)}
|
||||
valueLabel={stateCard.revenueNewProducts.description}
|
||||
percentLabel={stateCard.revenueNewProducts.descriptionPercent}
|
||||
/>
|
||||
|
|
@ -936,7 +944,7 @@ export function ProductInnovationPage() {
|
|||
<h3 className="font-bold text-base">{selectedProjectDetails?.title}</h3>
|
||||
<p className="py-2">{selectedProjectDetails?.project_description}</p>
|
||||
</div>
|
||||
<Timeline />
|
||||
<Timeline valueTimeLine={selectedProjectDetails?.current_status} />
|
||||
|
||||
{/* Technical Knowledge */}
|
||||
<div className=" rounded-lg py-2 mb-0">
|
||||
|
|
|
|||
|
|
@ -289,7 +289,7 @@ export function ProjectManagementPage() {
|
|||
const { scrollTop, scrollHeight, clientHeight } = scrollContainer;
|
||||
const scrollPercentage = (scrollTop + clientHeight) / scrollHeight;
|
||||
// Trigger load more when scrolled to 90% of the container
|
||||
if (scrollPercentage == 1) {
|
||||
if (scrollPercentage == 1 || scrollPercentage == .9) {
|
||||
loadMore();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -41,11 +41,11 @@ const chartConfig = {
|
|||
},
|
||||
};
|
||||
|
||||
const maxHeight = 150;
|
||||
const maxHeight = 150;
|
||||
const barHeights = () => Math.floor(Math.random() * maxHeight);
|
||||
|
||||
const ChartSkeleton = () => (
|
||||
|
||||
|
||||
<div className="flex justify-center h-96 w-full p-4">
|
||||
{/* Chart bars */}
|
||||
<div className=" w-full flex items-end gap-10">
|
||||
|
|
@ -131,7 +131,7 @@ export function StrategicAlignmentPopup({
|
|||
return (
|
||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||
<DialogContent className="w-full max-w-4xl bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] text-white border-none">
|
||||
<DialogHeader className="border-b-3 mb-10 py-2 w-full pb-4 border-b-2 border-gray-500/20">
|
||||
<DialogHeader className="mb-10 py-2 w-full pb-4 border-b-2 border-gray-500/20">
|
||||
<DialogTitle className="ml-auto text-sm text-white ">میزان انطباق راهبردی</DialogTitle>
|
||||
</DialogHeader>
|
||||
|
||||
|
|
@ -161,7 +161,7 @@ export function StrategicAlignmentPopup({
|
|||
return (
|
||||
<g transform={`translate(${x},${y})`}>
|
||||
<foreignObject width={80} height={20} x={-45} y={0}>
|
||||
<TruncatedText
|
||||
<TruncatedText
|
||||
maxWords={2}
|
||||
text={payload.value}
|
||||
/>
|
||||
|
|
@ -182,14 +182,14 @@ export function StrategicAlignmentPopup({
|
|||
|
||||
|
||||
label={{
|
||||
value: "تعداد برنامه ها" ,
|
||||
angle: -90,
|
||||
position: "insideLeft",
|
||||
value: "تعداد برنامه ها" ,
|
||||
angle: -90,
|
||||
position: "insideLeft",
|
||||
fill: "#94a3b8",
|
||||
fontSize: 11,
|
||||
offset: 0,
|
||||
dy: 0,
|
||||
style: { textAnchor: "middle" },
|
||||
dy: 0,
|
||||
style: { textAnchor: "middle" },
|
||||
}}
|
||||
/>
|
||||
|
||||
|
|
@ -209,7 +209,7 @@ export function StrategicAlignmentPopup({
|
|||
}}
|
||||
formatter={(v: number) => `${formatNumber(Math.round(v))}`}
|
||||
/>
|
||||
|
||||
|
||||
</Bar>
|
||||
</BarChart>
|
||||
</ChartContainer>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { formatNumber } from "~/lib/utils";
|
||||
import { formatNumber, calculateNiceRange } from "~/lib/utils";
|
||||
|
||||
export interface BarChartData {
|
||||
label: string;
|
||||
|
|
@ -29,10 +29,10 @@ export function CustomBarChart({
|
|||
className = "",
|
||||
loading = false,
|
||||
}: CustomBarChartProps) {
|
||||
// Calculate the maximum value across all data points for consistent scaling
|
||||
const globalMaxValue = Math.max(
|
||||
...data.map((item) => item.maxValue || item.value)
|
||||
);
|
||||
// استفاده از nice numbers برای محاسبه دامنه مناسب
|
||||
const values = data.map((item) => item.maxValue || item.value);
|
||||
const { niceMax, ticks } = calculateNiceRange(values, 0, 5);
|
||||
const globalMaxValue = niceMax;
|
||||
|
||||
// Loading skeleton
|
||||
if (loading) {
|
||||
|
|
@ -77,6 +77,7 @@ export function CustomBarChart({
|
|||
|
||||
<div className="space-y-4 px-4 pb-4">
|
||||
{data.map((item, index) => {
|
||||
// محاسبه درصد بر اساس nice max value
|
||||
const percentage =
|
||||
globalMaxValue > 0 ? (item.value / globalMaxValue) * 100 : 0;
|
||||
const displayValue: any = item.value;
|
||||
|
|
@ -106,7 +107,7 @@ export function CustomBarChart({
|
|||
<span className={`text-base font-normal text-left text-white`}>
|
||||
{item.valuePrefix || ""}
|
||||
|
||||
{formatNumber(parseFloat(displayValue))}
|
||||
{formatNumber(parseFloat(displayValue))}%
|
||||
{item.valueSuffix || ""}
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -114,24 +115,16 @@ export function CustomBarChart({
|
|||
);
|
||||
})}
|
||||
|
||||
{/* Axis Labels */}
|
||||
{/* Axis Labels با استفاده از nice numbers */}
|
||||
{showAxisLabels && globalMaxValue > 0 && (
|
||||
<div className="flex w-full items-center gap-3 mt-6">
|
||||
<span className="min-w-[120px]"></span>
|
||||
<div className="flex-1 flex justify-between pt-2 border-t border-gray-700">
|
||||
<span className="text-gray-400 text-xs">{formatNumber(0)}</span>
|
||||
<span className="text-gray-400 text-xs">
|
||||
{formatNumber(Math.round(globalMaxValue / 4))}
|
||||
</span>
|
||||
<span className="text-gray-400 text-xs">
|
||||
{formatNumber(Math.round(globalMaxValue / 2))}
|
||||
</span>
|
||||
<span className="text-gray-400 text-xs">
|
||||
{formatNumber(Math.round((globalMaxValue * 3) / 4))}
|
||||
</span>
|
||||
<span className="text-gray-400 text-xs">
|
||||
{formatNumber(Math.round(globalMaxValue))}
|
||||
</span>
|
||||
{ticks.map((tick, index) => (
|
||||
<span key={index} className="text-gray-400 text-xs">
|
||||
{formatNumber(tick)}%
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
<span className="min-w-[0px]"></span>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import * as React from "react"
|
||||
import * as ProgressPrimitive from "@radix-ui/react-progress"
|
||||
|
||||
import { cn } from "~/lib/utils"
|
||||
import { cn, formatNumber } from "~/lib/utils"
|
||||
|
||||
const Progress = React.forwardRef<
|
||||
React.ElementRef<typeof ProgressPrimitive.Root>,
|
||||
|
|
@ -10,14 +10,19 @@ const Progress = React.forwardRef<
|
|||
<ProgressPrimitive.Root
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"relative h-4 w-full overflow-hidden rounded-full bg-secondary",
|
||||
"relative h-4 w-full overflow-hidden rounded-full bg-pr-gray",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<span className="left-0 text-sm absolute z-10 px-2 text-[#5F6284]">۰%</span>
|
||||
<span className="w-full text-sm absolute z-10 px-2 text-[#5F6284]"
|
||||
style={{ transform: `translateX(-${10 - (value || 0)}%)` }}
|
||||
>{formatNumber(Math.ceil(value || 0 * 10) / 10)}%</span>
|
||||
<span className="right-0 text-sm absolute z-10 px-2 text-[#5F6284]">{formatNumber(.2)}%</span>
|
||||
<ProgressPrimitive.Indicator
|
||||
className="h-full w-full flex-1 bg-primary transition-all"
|
||||
style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
|
||||
style={{ transform: `translateX(-${20 - (value || 0)}%)` }}
|
||||
/>
|
||||
</ProgressPrimitive.Root>
|
||||
))
|
||||
|
|
|
|||
|
|
@ -24,6 +24,98 @@ export const formatCurrency = (amount: string | number) => {
|
|||
|
||||
|
||||
|
||||
/**
|
||||
* محاسبه دامنه nice numbers برای محور Y نمودارها
|
||||
* @param values آرایه از مقادیر دادهها
|
||||
* @param minValue حداقل مقدار (پیشفرض: 0 برای دادههای درصدی)
|
||||
* @param marginPercent درصد حاشیه اضافی (پیشفرض: 5%)
|
||||
* @returns شیء شامل حداکثر nice، فاصله tick ها، و آرایه tick ها
|
||||
*/
|
||||
export function calculateNiceRange(
|
||||
values: number[],
|
||||
minValue: number = 0,
|
||||
marginPercent: number = 5
|
||||
): {
|
||||
niceMax: number;
|
||||
tickInterval: number;
|
||||
ticks: number[];
|
||||
} {
|
||||
if (values.length === 0) {
|
||||
return { niceMax: 100, tickInterval: 20, ticks: [0, 20, 40, 60, 80, 100] };
|
||||
}
|
||||
|
||||
// پیدا کردن حداکثر مقدار در دادهها
|
||||
const dataMax = Math.max(...values);
|
||||
|
||||
// اگر همه مقادیر صفر یا منفی هستند
|
||||
if (dataMax <= 0) {
|
||||
return { niceMax: 100, tickInterval: 20, ticks: [0, 20, 40, 60, 80, 100] };
|
||||
}
|
||||
|
||||
// اضافه کردن حاشیه
|
||||
const maxWithMargin = dataMax * (1 + marginPercent / 100);
|
||||
|
||||
// محاسبه nice upper limit
|
||||
const niceMax = calculateNiceNumber(maxWithMargin, true);
|
||||
|
||||
// محاسبه فاصله مناسب tick ها بر اساس niceMax
|
||||
const range = niceMax - minValue;
|
||||
const targetTicks = 5; // هدف: 5 tick
|
||||
const roughTickInterval = range / (targetTicks - 1);
|
||||
const niceTickInterval = calculateNiceNumber(roughTickInterval, false);
|
||||
|
||||
// ایجاد آرایه tick ها
|
||||
const ticks: number[] = [];
|
||||
for (let i = minValue; i <= niceMax; i += niceTickInterval) {
|
||||
ticks.push(Math.round(i));
|
||||
}
|
||||
|
||||
// اطمینان از اینکه niceMax در آرایه tick ها باشد
|
||||
if (ticks[ticks.length - 1] !== niceMax) {
|
||||
ticks.push(niceMax);
|
||||
}
|
||||
|
||||
return {
|
||||
niceMax,
|
||||
tickInterval: niceTickInterval,
|
||||
ticks,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* محاسبه عدد nice (گرد و خوانا) بر اساس الگوریتم nice numbers
|
||||
* @param value مقدار ورودی
|
||||
* @param round آیا به سمت بالا گرد شود یا نه
|
||||
* @returns عدد nice
|
||||
*/
|
||||
function calculateNiceNumber(value: number, round: boolean): number {
|
||||
if (value <= 0) return 0;
|
||||
|
||||
// پیدا کردن قدرت 10
|
||||
const exponent = Math.floor(Math.log10(value));
|
||||
const fraction = value / Math.pow(10, exponent);
|
||||
|
||||
let niceFraction: number;
|
||||
|
||||
if (round) {
|
||||
// برای حداکثر: به سمت بالا گرد میکنیم با دقت بیشتر
|
||||
if (fraction <= 1.0) niceFraction = 1;
|
||||
else if (fraction <= 2.0) niceFraction = 2;
|
||||
else if (fraction <= 2.5) niceFraction = 2.5;
|
||||
else if (fraction <= 5.0) niceFraction = 5;
|
||||
else if (fraction <= 7.5) niceFraction = 7.5;
|
||||
else niceFraction = 10;
|
||||
} else {
|
||||
// برای فاصله tick ها: اعداد سادهتر
|
||||
if (fraction <= 1.0) niceFraction = 1;
|
||||
else if (fraction <= 2.0) niceFraction = 2;
|
||||
else if (fraction <= 5.0) niceFraction = 5;
|
||||
else niceFraction = 10;
|
||||
}
|
||||
|
||||
return niceFraction * Math.pow(10, exponent);
|
||||
}
|
||||
|
||||
export const handleDataValue = (val: any): any => {
|
||||
moment.loadPersian({ usePersianDigits: true });
|
||||
if (val == null) return val;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ const API_BASE_URL =
|
|||
// Import the CompanyDetails type
|
||||
import type { CompanyDetails } from "~/components/ecosystem/network-graph";
|
||||
import { formatNumber } from "~/lib/utils";
|
||||
import { Hexagon } from "lucide-react";
|
||||
|
||||
export function meta({}: Route.MetaArgs) {
|
||||
return [
|
||||
|
|
@ -164,18 +165,21 @@ export default function EcosystemPage() {
|
|||
</h3>
|
||||
{selectedCompany?.fields &&
|
||||
selectedCompany.fields.length > 0 ? (
|
||||
<div className="space-y-3 px-4">
|
||||
<div className="space-y-3 px-2">
|
||||
{selectedCompany.fields.map((field, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="flex justify-between items-center rounded-lg"
|
||||
>
|
||||
<span className="font-persian text-sm font-light">
|
||||
<span className="font-persian flex items-center gap-1 text-sm font-light">
|
||||
<Hexagon className="text-pr-green h-4 w-4" />
|
||||
{field.N}:
|
||||
</span>
|
||||
<span className="font-persian text-sm font-normal text-right">
|
||||
{handleValue(field.V)}
|
||||
{field.U && <span className="mr-1">({field.U})</span>}
|
||||
<span className="text-right min-w-1/3">
|
||||
<span className="font-persian text-sm font-normal text-right">
|
||||
{handleValue(field.V)}
|
||||
{field.U && <span className="mr-1">({field.U})</span>}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user