From 9d016a08cb9fa8d227fd799f257cea52a2bfe9a1 Mon Sep 17 00:00:00 2001 From: Chris Olson Date: Tue, 1 Sep 2026 09:19:38 -0400 Subject: [PATCH] Add CPM (Customer Portfolio Manager) attribute to accounts - New CPM field on AccountRecord type, DB schema, and migration - Seed "David Stefan" as CPM for 20 specified accounts - CPM filter dropdown on Account Explorer (alongside AD and IMS BA) - CPM shown on account cards, account detail view, and activity overlay - CPM column added to admin data table - upsertAccount includes CPM in insert/update Co-Authored-By: Claude Opus 4.6 --- src/app/(dashboard)/accounts/page.tsx | 29 +++++++++++++++++++++++---- src/app/(dashboard)/activity/page.tsx | 10 +++++++-- src/app/admin/page.tsx | 1 + src/lib/db.ts | 29 ++++++++++++++++++++++++--- src/lib/mock-data.ts | 1 + src/types/data.ts | 1 + 6 files changed, 62 insertions(+), 9 deletions(-) diff --git a/src/app/(dashboard)/accounts/page.tsx b/src/app/(dashboard)/accounts/page.tsx index 4418b7d..2b52563 100644 --- a/src/app/(dashboard)/accounts/page.tsx +++ b/src/app/(dashboard)/accounts/page.tsx @@ -111,6 +111,7 @@ export default function AccountExplorer() { const [renewalFilter, setRenewalFilter] = useState('all'); const [priorityFilter, setPriorityFilter] = useState(null); const [competitorFilter, setCompetitorFilter] = useState(null); + const [cpmFilter, setCpmFilter] = useState(null); const [selectedAccount, setSelectedAccount] = useState(null); const [showCreateOpp, setShowCreateOpp] = useState(false); const [showAddActivity, setShowAddActivity] = useState(false); @@ -177,6 +178,7 @@ export default function AccountExplorer() { const adValues = useMemo(() => Array.from(new Set(accounts.map(a => a.AD).filter(Boolean))).sort() as string[], [accounts]); const imsbaValues = useMemo(() => Array.from(new Set(accounts.map(a => a.IMS_BA).filter(Boolean))).sort() as string[], [accounts]); + const cpmValues = useMemo(() => Array.from(new Set(accounts.map(a => a.CPM).filter(Boolean))).sort() as string[], [accounts]); const filteredAccounts = useMemo(() => { const now = new Date(); @@ -190,6 +192,7 @@ export default function AccountExplorer() { if (districtFilter) result = result.filter(a => a.District_Name === districtFilter); if (adFilter) result = result.filter(a => a.AD === adFilter); if (imsbaFilter) result = result.filter(a => a.IMS_BA === imsbaFilter); + if (cpmFilter) result = result.filter(a => a.CPM === cpmFilter); if (priorityFilter) result = result.filter(a => a.Priority === priorityFilter); if (competitorFilter) result = result.filter(a => { const comps = (a.Competitors || '').split(',').map(c => c.trim()).filter(Boolean); @@ -213,7 +216,7 @@ export default function AccountExplorer() { } } return result; - }, [accounts, search, tierFilter, statusFilter, districtFilter, adFilter, imsbaFilter, renewalFilter, priorityFilter, competitorFilter]); + }, [accounts, search, tierFilter, statusFilter, districtFilter, adFilter, imsbaFilter, cpmFilter, renewalFilter, priorityFilter, competitorFilter]); const kpis = useMemo(() => { const acctNames = new Set(filteredAccounts.map(a => a.Account_Name)); @@ -292,11 +295,12 @@ export default function AccountExplorer() { setImsbaFilter(null); setPriorityFilter(null); setCompetitorFilter(null); + setCpmFilter(null); setRenewalFilter('all'); setSearch(''); }; - const hasFilters = tierFilter || statusFilter || districtFilter || adFilter || imsbaFilter || priorityFilter || competitorFilter || renewalFilter !== 'all' || search; + const hasFilters = tierFilter || statusFilter || districtFilter || adFilter || imsbaFilter || cpmFilter || priorityFilter || competitorFilter || renewalFilter !== 'all' || search; if (selectedAccount) { const suggestion = getSuggestedPriority(selectedAccount); @@ -395,8 +399,8 @@ export default function AccountExplorer() { )} - {(selectedAccount.AD || selectedAccount.IMS_BA || selectedAccount.Area_Sales_Leader || selectedAccount.DM) && ( -
+ {(selectedAccount.AD || selectedAccount.IMS_BA || selectedAccount.CPM || selectedAccount.Area_Sales_Leader || selectedAccount.DM) && ( +
{selectedAccount.Area_Sales_Leader && (
Area Sales Leader
@@ -421,6 +425,12 @@ export default function AccountExplorer() {
{selectedAccount.IMS_BA}
)} + {selectedAccount.CPM && ( +
+
CPM
+
{selectedAccount.CPM}
+
+ )}
)}
@@ -815,6 +825,16 @@ export default function AccountExplorer() { {imsbaValues.map(v => )} )} + {cpmValues.length > 0 && ( + + )}