Add Planned activities column to Exec Summary district table

Split the Activities column into Activities (occurred) and Planned
(future) to match the Executive Overview's District Performance chart.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-09-04 12:21:34 -04:00
parent c8c867ff66
commit c4f02a84c8

View File

@@ -80,11 +80,12 @@ export default function ExecutiveSummary() {
}, [accounts]);
const districtPerformance = useMemo(() => {
const districts = new Map<string, { pipeline: number; activities: number; accountsTouched: Set<string>; totalAccounts: number }>();
const todayStr = format(now, 'yyyy-MM-dd');
const districts = new Map<string, { pipeline: number; activities: number; planned: number; accountsTouched: Set<string>; totalAccounts: number }>();
accounts.forEach(a => {
const d = DISTRICT_SHORT[a.District_Name] || a.District_Name;
if (!districts.has(d)) districts.set(d, { pipeline: 0, activities: 0, accountsTouched: new Set(), totalAccounts: 0 });
if (!districts.has(d)) districts.set(d, { pipeline: 0, activities: 0, planned: 0, accountsTouched: new Set(), totalAccounts: 0 });
const entry = districts.get(d)!;
entry.totalAccounts++;
if ((a.Touch_Count || 0) > 0) entry.accountsTouched.add(a.Account_Name);
@@ -92,14 +93,19 @@ export default function ExecutiveSummary() {
pipeline.filter(p => p.Stage !== '06-Closed Won' && p.Stage !== '07-Closed Lost').forEach(p => {
const d = DISTRICT_SHORT[p.District_Name] || p.District_Name;
if (!districts.has(d)) districts.set(d, { pipeline: 0, activities: 0, accountsTouched: new Set(), totalAccounts: 0 });
if (!districts.has(d)) districts.set(d, { pipeline: 0, activities: 0, planned: 0, accountsTouched: new Set(), totalAccounts: 0 });
districts.get(d)!.pipeline += p.Amount_USD;
});
activities.forEach(a => {
const d = DISTRICT_SHORT[a.District_Name] || a.District_Name;
if (!districts.has(d)) districts.set(d, { pipeline: 0, activities: 0, accountsTouched: new Set(), totalAccounts: 0 });
districts.get(d)!.activities++;
if (!districts.has(d)) districts.set(d, { pipeline: 0, activities: 0, planned: 0, accountsTouched: new Set(), totalAccounts: 0 });
const entry = districts.get(d)!;
if (a.Status === 'Planned' || a.Activity_Date > todayStr) {
entry.planned++;
} else {
entry.activities++;
}
});
return Array.from(districts.entries())
@@ -107,11 +113,12 @@ export default function ExecutiveSummary() {
name,
pipeline: data.pipeline,
activities: data.activities,
planned: data.planned,
accountsTouched: data.accountsTouched.size,
totalAccounts: data.totalAccounts,
}))
.sort((a, b) => b.pipeline - a.pipeline);
}, [pipeline, accounts, activities]);
}, [pipeline, accounts, activities, now]);
const keyWins = useMemo(() => {
return pipeline
@@ -290,6 +297,7 @@ export default function ExecutiveSummary() {
<th className="text-left py-1.5 font-medium text-gray-600 text-xs">District</th>
<th className="text-right py-1.5 font-medium text-gray-600 text-xs">Pipeline</th>
<th className="text-right py-1.5 font-medium text-gray-600 text-xs">Activities</th>
<th className="text-right py-1.5 font-medium text-gray-600 text-xs">Planned</th>
<th className="text-right py-1.5 font-medium text-gray-600 text-xs">Touched</th>
</tr>
</thead>
@@ -299,6 +307,7 @@ export default function ExecutiveSummary() {
<td className="py-1.5 font-medium text-gray-700">{d.name}</td>
<td className="py-1.5 text-right text-gray-700">{formatCurrency(d.pipeline, true)}</td>
<td className="py-1.5 text-right text-gray-700">{d.activities}</td>
<td className="py-1.5 text-right text-gray-700">{d.planned}</td>
<td className="py-1.5 text-right text-gray-700">
{d.accountsTouched}/{d.totalAccounts}
</td>