This commit is contained in:
MehrdadAdabi 2025-10-08 18:48:54 +03:30
commit 584450550b
9 changed files with 42 additions and 37 deletions

View File

@ -594,7 +594,7 @@ export function DashboardHome() {
<p className="p-6 font-persian font-semibold text-lg ">
تحقق ارزش ها
</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>

View File

@ -932,15 +932,7 @@ export function ManageIdeasTechPage() {
{/* Infinite scroll trigger */}
<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>
</CardContent>
@ -951,6 +943,15 @@ export function ManageIdeasTechPage() {
</div>
</div>
</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>
{/* Chart Section */}
<BaseCard icon={TrendingUp} className="col-span-1 mt-12 row-start-2 col-start-3 row-span-1" title="نمودار ایده‌ها">

View File

@ -237,11 +237,11 @@ export function ProductInnovationPage() {
revenueNewProducts: {
id: "revenueNewProducts",
title: "سهم از درآمد برای محصولات جدید",
value: "0",
value: 0,
description: "میلیون ریال",
descriptionPercent: "درصد به کل درآمد",
color: "text-[#3AEA83]",
percent : "0"
percent :0
},
newProductExports: {
id: "newProductExports",
@ -466,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: normalized.new_products_revenue_share,
percent: normalized.new_products_revenue_share_percent,
},
impactOnImports: {
...prev.impactOnImports,
@ -716,8 +716,8 @@ export function ProductInnovationPage() {
<div className="col-span-2">
<MetricCard
title={stateCard.revenueNewProducts.title}
value={formatNumber(stateCard.revenueNewProducts.value)}
percentValue={formatNumber(stateCard.revenueNewProducts.percent)}
value={stateCard.revenueNewProducts.value}
percentValue={stateCard.revenueNewProducts.percent}
valueLabel={stateCard.revenueNewProducts.description}
percentLabel={stateCard.revenueNewProducts.descriptionPercent}
/>
@ -756,7 +756,7 @@ export function ProductInnovationPage() {
</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">
<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">
<FunnelChart
title="قيف فرآیند پروژه ها"

View File

@ -24,7 +24,7 @@ import { TruncatedText } from "../ui/truncatedText";
interface StrategicAlignmentData {
strategic_theme: string;
operational_fee_sum: number;
operational_fee_count: number;
percentage?: number;
}
@ -138,7 +138,7 @@ export function StrategicAlignmentPopup({
ProcessName: "project",
OutputFields: [
"strategic_theme",
"sum(operational_fee) as operational_fee_sum",
"count(operational_fee)",
],
GroupBy: ["strategic_theme"],
});
@ -168,7 +168,7 @@ export function StrategicAlignmentPopup({
ProcessName: "project",
OutputFields: [
"value_technology_and_innovation",
"sum(operational_fee)",
"count(operational_fee)",
],
Conditions: [["strategic_theme", "=", item]],
GroupBy: ["value_technology_and_innovation"],
@ -233,13 +233,13 @@ export function StrategicAlignmentPopup({
.map((item: any) => ({
strategic_theme:
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 !== "");
const total = processedData.reduce(
(acc: number, item: StrategicAlignmentData) =>
acc + item.operational_fee_sum,
acc + item.operational_fee_count,
0
);
@ -247,7 +247,7 @@ export function StrategicAlignmentPopup({
(item: StrategicAlignmentData) => ({
...item,
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 || []);

View File

@ -305,7 +305,7 @@ export function NetworkGraph({ onNodeClick, onLoadingChange }: NetworkGraphProps
.enter()
.append("g")
.attr("class", "node")
.style("cursor", "pointer");
.style("cursor", d => d.stageid === -1 ? "default" : "pointer");
const drag = d3
.drag<SVGGElement, Node>()
@ -437,9 +437,12 @@ export function NetworkGraph({ onNodeClick, onLoadingChange }: NetworkGraphProps
.attr("stroke-width", 3);
});
nodeGroup.on("click", async function (event, d) {
event.stopPropagation();
if (d.isCenter) return;
// جلوگیری از کلیک روی مرکز و دسته‌بندی‌ها
if (d.isCenter || d.stageid === -1) return;
if (onNodeClick && d.stageid) {
// Open dialog immediately with basic info

View File

@ -13,6 +13,7 @@ interface FunnelChartProps {
title?: string;
className?: string;
}
const greenColors = ["#3C9F71","#3BC47A","#3BC47A","#3BD77E","#3AEA83"]
export function FunnelChart({ data, title, className = "" }: FunnelChartProps) {
const maxValue = Math.max(...data.map(d => d.value));
@ -50,15 +51,15 @@ export function FunnelChart({ data, title, className = "" }: FunnelChartProps) {
return (
<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}
</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 style={{ width: `${(100 - barWidth) / 2}%` }} />
<div
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">
{item.value.toLocaleString('fa-IR')}

View File

@ -19,7 +19,7 @@ const Progress = React.forwardRef<
<span className="w-full right-0 text-sm absolute z-10 px-2 text-[#5F6284]"
>{formatNumber(Math.ceil(value || 0 * 10) / 10)}%</span>
<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)}%)` }}
/>
</ProgressPrimitive.Root>

View File

@ -81,7 +81,7 @@ export function TabsTrigger({
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",
isActive
? "bg-gray-700 text-foreground shadow-sm"
? "bg-pr-gray text-foreground shadow-sm"
: "hover:bg-muted/50",
className,
)}