From a1f1b33e449cb5864a52cc902df07e42aa8c4e73 Mon Sep 17 00:00:00 2001 From: RKWojs Date: Fri, 14 Nov 2025 12:24:41 +0100 Subject: [PATCH] feat: enhance TeamLeadsDashboard with detailed realised vs unrealised values by project type and improved chart visualization --- src/app/api/dashboard/route.js | 66 ++++++++++++-- src/app/dashboard/page.js | 162 ++++++++++++++++++++++----------- 2 files changed, 166 insertions(+), 62 deletions(-) diff --git a/src/app/api/dashboard/route.js b/src/app/api/dashboard/route.js index b21eef5..8421797 100644 --- a/src/app/api/dashboard/route.js +++ b/src/app/api/dashboard/route.js @@ -21,20 +21,39 @@ export async function GET(request) { // Get all projects const projects = getAllProjects(); - // Calculate realised and unrealised values - let realisedValue = 0; - let unrealisedValue = 0; + // Calculate realised and unrealised values by project type + const projectTypes = ['design', 'design+construction', 'construction']; + const typeSummary = {}; + + projectTypes.forEach(type => { + typeSummary[type] = { + realisedValue: 0, + unrealisedValue: 0 + }; + }); projects.forEach(project => { const value = parseFloat(project.wartosc_zlecenia) || 0; + const type = project.project_type; + + if (!type || !projectTypes.includes(type)) return; + if (project.project_status === 'fulfilled' && project.completion_date && project.wartosc_zlecenia) { - realisedValue += value; + typeSummary[type].realisedValue += value; } else if (project.wartosc_zlecenia && project.project_status !== 'cancelled') { - // Count all non-cancelled projects with values as unrealised - unrealisedValue += value; + typeSummary[type].unrealisedValue += value; } }); + // Calculate overall totals + let realisedValue = 0; + let unrealisedValue = 0; + + Object.values(typeSummary).forEach(summary => { + realisedValue += summary.realisedValue; + unrealisedValue += summary.unrealisedValue; + }); + // Filter completed projects (those with completion_date and fulfilled status) const completedProjects = projects.filter(project => project.completion_date && @@ -61,8 +80,24 @@ export async function GET(request) { { month: 'Dec 2024', value: 95000, cumulative: 958000 } ]; summary = { - realisedValue: 958000, - unrealisedValue: 1242000 + total: { + realisedValue: 958000, + unrealisedValue: 1242000 + }, + byType: { + design: { + realisedValue: 320000, + unrealisedValue: 480000 + }, + 'design+construction': { + realisedValue: 480000, + unrealisedValue: 520000 + }, + construction: { + realisedValue: 158000, + unrealisedValue: 242000 + } + } }; } else { // Group by month and calculate monthly totals first @@ -112,8 +147,19 @@ export async function GET(request) { return NextResponse.json({ chartData, summary: { - realisedValue: Math.round(realisedValue), - unrealisedValue: Math.round(unrealisedValue) + total: { + realisedValue: Math.round(realisedValue), + unrealisedValue: Math.round(unrealisedValue) + }, + byType: Object.fromEntries( + Object.entries(typeSummary).map(([type, data]) => [ + type, + { + realisedValue: Math.round(data.realisedValue), + unrealisedValue: Math.round(data.unrealisedValue) + } + ]) + ) } }); diff --git a/src/app/dashboard/page.js b/src/app/dashboard/page.js index 744f32b..f51d27c 100644 --- a/src/app/dashboard/page.js +++ b/src/app/dashboard/page.js @@ -127,64 +127,122 @@ export default function TeamLeadsDashboard() { )} -
-

- Realised vs Unrealised Value -

+
+ {/* Main Total Chart */} +
+

+ Total Portfolio +

- {summaryData ? ( -
- - - `${name}: ${(percent * 100).toFixed(0)}%`} - > - - - - formatCurrency(value)} /> - - - -
- ) : ( -
-
No summary data available
-
- )} + {summaryData?.total ? ( +
+ + + `${name}: ${(percent * 100).toFixed(0)}%`} + > + + + + formatCurrency(value)} /> + + + +
+ ) : ( +
+
No summary data available
+
+ )} - {summaryData && ( -
-
-
Realised Value
-
- {formatCurrency(summaryData.realisedValue)} + {summaryData?.total && ( +
+
+
Realised Value
+
+ {formatCurrency(summaryData.total.realisedValue)} +
+
+
+
Unrealised Value
+
+ {formatCurrency(summaryData.total.unrealisedValue)} +
-
-
Unrealised Value
-
- {formatCurrency(summaryData.unrealisedValue)} + )} +
+ + {/* Project Type Charts */} +
+

+ By Project Type +

+ +
+ {summaryData?.byType && Object.entries(summaryData.byType).map(([type, data]) => ( +
+

+ {type.replace('+', ' + ')} +

+ + {/* Mini pie chart */} +
+ + + percent > 0.1 ? `${(percent * 100).toFixed(0)}%` : ''} + > + + + + formatCurrency(value)} /> + + +
+ +
+
+ Realised + + {formatCurrency(data.realisedValue)} + +
+
+ Unrealised + + {formatCurrency(data.unrealisedValue)} + +
+
-
+ ))}
- )} +