Merge branch 'main' of http://git.sepehrdata.com/Saeed0920/inogen
This commit is contained in:
commit
584450550b
|
|
@ -594,8 +594,8 @@ export function DashboardHome() {
|
||||||
<p className="p-6 font-persian font-semibold text-lg ">
|
<p className="p-6 font-persian font-semibold text-lg ">
|
||||||
تحقق ارزش ها
|
تحقق ارزش ها
|
||||||
</p>
|
</p>
|
||||||
<TabsList className="bg-transparent py-2 border m-6 border-gray-600">
|
<TabsList className="bg-transparent py-2 m-6 border-[1px] border-[#5F6284]">
|
||||||
<TabsTrigger value="canvas" className="cursor-pointer">
|
<TabsTrigger value="canvas" className="cursor-pointer">
|
||||||
شماتیک
|
شماتیک
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
<TabsTrigger value="charts" className=" text-white cursor-pointer font-light ">
|
<TabsTrigger value="charts" className=" text-white cursor-pointer font-light ">
|
||||||
|
|
|
||||||
|
|
@ -932,15 +932,7 @@ export function ManageIdeasTechPage() {
|
||||||
|
|
||||||
{/* Infinite scroll trigger */}
|
{/* Infinite scroll trigger */}
|
||||||
<div ref={observerRef} className="h-auto">
|
<div ref={observerRef} className="h-auto">
|
||||||
{loadingMore && (
|
|
||||||
<div className="flex items-center justify-center py-2">
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<RefreshCw className="w-4 h-4 animate-spin text-success" />
|
|
||||||
<span className="font-persian text-muted-foreground text-sm">
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|
||||||
|
|
@ -951,6 +943,15 @@ export function ManageIdeasTechPage() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
{loadingMore && (
|
||||||
|
<div className="flex items-center justify-center py-2">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<RefreshCw className="w-4 h-4 animate-spin text-success" />
|
||||||
|
<span className="font-persian text-muted-foreground text-sm">
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
{/* Chart Section */}
|
{/* Chart Section */}
|
||||||
<BaseCard icon={TrendingUp} className="col-span-1 mt-12 row-start-2 col-start-3 row-span-1" title="نمودار ایدهها">
|
<BaseCard icon={TrendingUp} className="col-span-1 mt-12 row-start-2 col-start-3 row-span-1" title="نمودار ایدهها">
|
||||||
|
|
|
||||||
|
|
@ -237,11 +237,11 @@ export function ProductInnovationPage() {
|
||||||
revenueNewProducts: {
|
revenueNewProducts: {
|
||||||
id: "revenueNewProducts",
|
id: "revenueNewProducts",
|
||||||
title: "سهم از درآمد برای محصولات جدید",
|
title: "سهم از درآمد برای محصولات جدید",
|
||||||
value: "0",
|
value: 0,
|
||||||
description: "میلیون ریال",
|
description: "میلیون ریال",
|
||||||
descriptionPercent: "درصد به کل درآمد",
|
descriptionPercent: "درصد به کل درآمد",
|
||||||
color: "text-[#3AEA83]",
|
color: "text-[#3AEA83]",
|
||||||
percent : "0"
|
percent :0
|
||||||
},
|
},
|
||||||
newProductExports: {
|
newProductExports: {
|
||||||
id: "newProductExports",
|
id: "newProductExports",
|
||||||
|
|
@ -466,8 +466,8 @@ export function ProductInnovationPage() {
|
||||||
...prev,
|
...prev,
|
||||||
revenueNewProducts: {
|
revenueNewProducts: {
|
||||||
...prev.revenueNewProducts,
|
...prev.revenueNewProducts,
|
||||||
value: formatNumber(normalized?.new_products_revenue_share),
|
value: normalized.new_products_revenue_share,
|
||||||
percent: formatNumber(normalized?.new_products_revenue_share_percent),
|
percent: normalized.new_products_revenue_share_percent,
|
||||||
},
|
},
|
||||||
impactOnImports: {
|
impactOnImports: {
|
||||||
...prev.impactOnImports,
|
...prev.impactOnImports,
|
||||||
|
|
@ -716,8 +716,8 @@ export function ProductInnovationPage() {
|
||||||
<div className="col-span-2">
|
<div className="col-span-2">
|
||||||
<MetricCard
|
<MetricCard
|
||||||
title={stateCard.revenueNewProducts.title}
|
title={stateCard.revenueNewProducts.title}
|
||||||
value={formatNumber(stateCard.revenueNewProducts.value)}
|
value={stateCard.revenueNewProducts.value}
|
||||||
percentValue={formatNumber(stateCard.revenueNewProducts.percent)}
|
percentValue={stateCard.revenueNewProducts.percent}
|
||||||
valueLabel={stateCard.revenueNewProducts.description}
|
valueLabel={stateCard.revenueNewProducts.description}
|
||||||
percentLabel={stateCard.revenueNewProducts.descriptionPercent}
|
percentLabel={stateCard.revenueNewProducts.descriptionPercent}
|
||||||
/>
|
/>
|
||||||
|
|
@ -756,7 +756,7 @@ export function ProductInnovationPage() {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Funnel Chart */}
|
{/* Funnel Chart */}
|
||||||
<Card className="bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] h-full backdrop-blur-sm rounded-2xl w-full overflow-hidden">
|
<Card className=" bg-[linear-gradient(to_bottom_left,#464861,50%,#111628)] h-full 2xl:h-auto pb-8 backdrop-blur-sm rounded-2xl w-full overflow-hidden">
|
||||||
<CardContent className="px-0 py-4">
|
<CardContent className="px-0 py-4">
|
||||||
<FunnelChart
|
<FunnelChart
|
||||||
title="قيف فرآیند پروژه ها"
|
title="قيف فرآیند پروژه ها"
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ import { TruncatedText } from "../ui/truncatedText";
|
||||||
|
|
||||||
interface StrategicAlignmentData {
|
interface StrategicAlignmentData {
|
||||||
strategic_theme: string;
|
strategic_theme: string;
|
||||||
operational_fee_sum: number;
|
operational_fee_count: number;
|
||||||
percentage?: number;
|
percentage?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -138,7 +138,7 @@ export function StrategicAlignmentPopup({
|
||||||
ProcessName: "project",
|
ProcessName: "project",
|
||||||
OutputFields: [
|
OutputFields: [
|
||||||
"strategic_theme",
|
"strategic_theme",
|
||||||
"sum(operational_fee) as operational_fee_sum",
|
"count(operational_fee)",
|
||||||
],
|
],
|
||||||
GroupBy: ["strategic_theme"],
|
GroupBy: ["strategic_theme"],
|
||||||
});
|
});
|
||||||
|
|
@ -168,7 +168,7 @@ export function StrategicAlignmentPopup({
|
||||||
ProcessName: "project",
|
ProcessName: "project",
|
||||||
OutputFields: [
|
OutputFields: [
|
||||||
"value_technology_and_innovation",
|
"value_technology_and_innovation",
|
||||||
"sum(operational_fee)",
|
"count(operational_fee)",
|
||||||
],
|
],
|
||||||
Conditions: [["strategic_theme", "=", item]],
|
Conditions: [["strategic_theme", "=", item]],
|
||||||
GroupBy: ["value_technology_and_innovation"],
|
GroupBy: ["value_technology_and_innovation"],
|
||||||
|
|
@ -233,13 +233,13 @@ export function StrategicAlignmentPopup({
|
||||||
.map((item: any) => ({
|
.map((item: any) => ({
|
||||||
strategic_theme:
|
strategic_theme:
|
||||||
item.strategic_theme || item.value_technology_and_innovation || "N/A",
|
item.strategic_theme || item.value_technology_and_innovation || "N/A",
|
||||||
operational_fee_sum: Math.max(0, Number(item.operational_fee_sum)),
|
operational_fee_count: Math.max(0, Number(item.operational_fee_count)),
|
||||||
}))
|
}))
|
||||||
.filter((item: StrategicAlignmentData) => item.strategic_theme !== "");
|
.filter((item: StrategicAlignmentData) => item.strategic_theme !== "");
|
||||||
|
|
||||||
const total = processedData.reduce(
|
const total = processedData.reduce(
|
||||||
(acc: number, item: StrategicAlignmentData) =>
|
(acc: number, item: StrategicAlignmentData) =>
|
||||||
acc + item.operational_fee_sum,
|
acc + item.operational_fee_count,
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -247,7 +247,7 @@ export function StrategicAlignmentPopup({
|
||||||
(item: StrategicAlignmentData) => ({
|
(item: StrategicAlignmentData) => ({
|
||||||
...item,
|
...item,
|
||||||
percentage:
|
percentage:
|
||||||
total > 0 ? Math.round((item.operational_fee_sum / total) * 100) : 0,
|
total > 0 ? Math.round((item.operational_fee_count / total) * 100) : 0,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
setData(dataWithPercentage || []);
|
setData(dataWithPercentage || []);
|
||||||
|
|
|
||||||
|
|
@ -305,7 +305,7 @@ export function NetworkGraph({ onNodeClick, onLoadingChange }: NetworkGraphProps
|
||||||
.enter()
|
.enter()
|
||||||
.append("g")
|
.append("g")
|
||||||
.attr("class", "node")
|
.attr("class", "node")
|
||||||
.style("cursor", "pointer");
|
.style("cursor", d => d.stageid === -1 ? "default" : "pointer");
|
||||||
|
|
||||||
const drag = d3
|
const drag = d3
|
||||||
.drag<SVGGElement, Node>()
|
.drag<SVGGElement, Node>()
|
||||||
|
|
@ -437,9 +437,12 @@ export function NetworkGraph({ onNodeClick, onLoadingChange }: NetworkGraphProps
|
||||||
.attr("stroke-width", 3);
|
.attr("stroke-width", 3);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
nodeGroup.on("click", async function (event, d) {
|
nodeGroup.on("click", async function (event, d) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
if (d.isCenter) return;
|
|
||||||
|
// جلوگیری از کلیک روی مرکز و دستهبندیها
|
||||||
|
if (d.isCenter || d.stageid === -1) return;
|
||||||
|
|
||||||
if (onNodeClick && d.stageid) {
|
if (onNodeClick && d.stageid) {
|
||||||
// Open dialog immediately with basic info
|
// Open dialog immediately with basic info
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ interface FunnelChartProps {
|
||||||
title?: string;
|
title?: string;
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
const greenColors = ["#3C9F71","#3BC47A","#3BC47A","#3BD77E","#3AEA83"]
|
||||||
|
|
||||||
export function FunnelChart({ data, title, className = "" }: FunnelChartProps) {
|
export function FunnelChart({ data, title, className = "" }: FunnelChartProps) {
|
||||||
const maxValue = Math.max(...data.map(d => d.value));
|
const maxValue = Math.max(...data.map(d => d.value));
|
||||||
|
|
@ -50,15 +51,15 @@ export function FunnelChart({ data, title, className = "" }: FunnelChartProps) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={index} className="grid grid-cols-[6rem_1fr] gap-2 w-full">
|
<div key={index} className="grid grid-cols-[6rem_1fr] gap-2 w-full">
|
||||||
<div className="text-sm font-light text-white cols-start-1 justify-self-start font-thin min-w-[max-content] text-center">
|
<div className="text-sm font-light text-white font-persian cols-start-1 justify-self-start min-w-[max-content] text-center">
|
||||||
{item.label}
|
{item.label}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-10 w-full cols-start-2 flex items-center justify-center w-full">
|
<div className="flex items-center gap-10 w-full cols-start-2 justify-center">
|
||||||
<div className="flex items-center w-full">
|
<div className="flex items-center w-full">
|
||||||
<div style={{ width: `${(100 - barWidth) / 2}%` }} />
|
<div style={{ width: `${(100 - barWidth) / 2}%` }} />
|
||||||
<div
|
<div
|
||||||
className="bg-[#3BC47A] h-8 rounded-2xl flex items-center justify-center text-lg relative"
|
className="bg-[#3BC47A] h-8 rounded-2xl flex items-center justify-center text-lg relative"
|
||||||
style={{ width: `${barWidth}%` }}
|
style={{ width: `${barWidth}%` ,backgroundColor : `${greenColors[index]}`}}
|
||||||
>
|
>
|
||||||
<span className="text-pr-gray text-base font-semibold">
|
<span className="text-pr-gray text-base font-semibold">
|
||||||
{item.value.toLocaleString('fa-IR')}
|
{item.value.toLocaleString('fa-IR')}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ const Progress = React.forwardRef<
|
||||||
<span className="w-full right-0 text-sm absolute z-10 px-2 text-[#5F6284]"
|
<span className="w-full right-0 text-sm absolute z-10 px-2 text-[#5F6284]"
|
||||||
>{formatNumber(Math.ceil(value || 0 * 10) / 10)}%</span>
|
>{formatNumber(Math.ceil(value || 0 * 10) / 10)}%</span>
|
||||||
<ProgressPrimitive.Indicator
|
<ProgressPrimitive.Indicator
|
||||||
className="h-full w-full flex-1 bg-primary transition-all"
|
className="h-full w-full flex-1 bg-pr-green transition-all"
|
||||||
style={{ transform: `translateX(-${15 - (value || 0)}%)` }}
|
style={{ transform: `translateX(-${15 - (value || 0)}%)` }}
|
||||||
/>
|
/>
|
||||||
</ProgressPrimitive.Root>
|
</ProgressPrimitive.Root>
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ export function TabsTrigger({
|
||||||
className={cn(
|
className={cn(
|
||||||
"inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
|
"inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
|
||||||
isActive
|
isActive
|
||||||
? "bg-gray-700 text-foreground shadow-sm"
|
? "bg-pr-gray text-foreground shadow-sm"
|
||||||
: "hover:bg-muted/50",
|
: "hover:bg-muted/50",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user