Add inline priority editing on account detail page
- Clickable priority badge with dropdown to change High/Medium/Low - New account.priority API action for lightweight single-field update - Larger priority badges on account cards (text-[10px] font-bold) - Add FedEx Freight Inc. to database, remove TechFarce - Update 17 AD assignments from FY26 team mapping spreadsheet Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -158,6 +158,7 @@ export default function AccountExplorer() {
|
||||
const [showCreateOpp, setShowCreateOpp] = useState(false);
|
||||
const [showAddActivity, setShowAddActivity] = useState(false);
|
||||
const [saving, setSaving] = useState(false);
|
||||
const [editingPriority, setEditingPriority] = useState(false);
|
||||
const searchParams = useSearchParams();
|
||||
|
||||
useEffect(() => {
|
||||
@@ -371,7 +372,40 @@ export default function AccountExplorer() {
|
||||
<div className="flex flex-wrap items-center gap-2 mt-2">
|
||||
<span className="px-2 py-0.5 rounded-full text-[10px] text-white font-semibold" style={{ backgroundColor: TIER_COLORS[selectedAccount.Tier] || '#94A3B8' }}>{selectedAccount.Tier || 'N/A'}</span>
|
||||
<span className="px-2 py-0.5 rounded-full text-[10px] text-white font-semibold" style={{ backgroundColor: STATUS_COLORS[selectedAccount.AgentMinder_Status] || '#94A3B8' }}>{selectedAccount.AgentMinder_Status}</span>
|
||||
<span className="px-2 py-0.5 rounded-full text-[10px] text-white font-semibold" style={{ backgroundColor: PRIORITY_COLORS[selectedAccount.Priority] || '#94A3B8' }}>{selectedAccount.Priority} Priority</span>
|
||||
<span className="relative">
|
||||
<button
|
||||
onClick={() => setEditingPriority(!editingPriority)}
|
||||
className="px-2 py-0.5 rounded-full text-[10px] text-white font-semibold cursor-pointer hover:ring-2 hover:ring-offset-1 hover:ring-brand-azure transition"
|
||||
style={{ backgroundColor: PRIORITY_COLORS[selectedAccount.Priority] || '#94A3B8' }}
|
||||
title="Click to change priority"
|
||||
>
|
||||
{selectedAccount.Priority} Priority ▾
|
||||
</button>
|
||||
{editingPriority && (
|
||||
<div className="absolute top-full left-0 mt-1 bg-card-bg border border-card-border rounded-lg shadow-lg z-50 py-1 min-w-[120px]">
|
||||
{['High', 'Medium', 'Low'].map(p => (
|
||||
<button
|
||||
key={p}
|
||||
onClick={async () => {
|
||||
await fetch('/api/phase2', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ action: 'account.priority', Account_Name: selectedAccount.Account_Name, Priority: p }),
|
||||
});
|
||||
setEditingPriority(false);
|
||||
setSelectedAccount({ ...selectedAccount, Priority: p });
|
||||
refresh();
|
||||
}}
|
||||
className={`w-full text-left px-3 py-1.5 text-xs font-medium flex items-center gap-2 hover:bg-gray-100 transition ${selectedAccount.Priority === p ? 'font-bold' : ''}`}
|
||||
>
|
||||
<span className="w-2.5 h-2.5 rounded-full flex-shrink-0" style={{ backgroundColor: PRIORITY_COLORS[p] }} />
|
||||
{p}
|
||||
{selectedAccount.Priority === p && <span className="ml-auto text-brand-azure">✓</span>}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</span>
|
||||
<span className="px-2 py-0.5 rounded-full text-[10px] font-bold" style={{ color: HEALTH_LEVEL_COLORS[detailHealth.health_level], backgroundColor: `${HEALTH_LEVEL_COLORS[detailHealth.health_level]}15` }}>
|
||||
Health: {detailHealth.health_level} ({detailHealth.health_score})
|
||||
</span>
|
||||
@@ -1015,7 +1049,7 @@ export default function AccountExplorer() {
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5 mb-2">
|
||||
<span className="px-1.5 py-0.5 rounded text-[9px] font-medium text-white" style={{ backgroundColor: PRIORITY_COLORS[account.Priority] || '#94A3B8' }}>{account.Priority}</span>
|
||||
<span className="px-2 py-0.5 rounded text-[10px] font-bold text-white" style={{ backgroundColor: PRIORITY_COLORS[account.Priority] || '#94A3B8' }}>{account.Priority}</span>
|
||||
<span className="px-1.5 py-0.5 rounded text-[9px] font-medium text-white" style={{ backgroundColor: STATUS_COLORS[account.AgentMinder_Status] || '#94A3B8' }}>{account.AgentMinder_Status}</span>
|
||||
<span className="text-[10px] text-muted">{DISTRICT_SHORT[account.District_Name]}</span>
|
||||
{account.AD && <span className="text-[10px] text-muted">| {account.AD}</span>}
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
getForecastLocks, lockForecast, getForecastOverrides, upsertForecastOverride, deleteForecastOverride,
|
||||
getPipelineMovement, getSnapshotDates,
|
||||
updateLossReason,
|
||||
updateAccountPriority,
|
||||
} from '@/lib/db';
|
||||
|
||||
export async function POST(req: NextRequest) {
|
||||
@@ -96,6 +97,10 @@ export async function POST(req: NextRequest) {
|
||||
updateLossReason(body.Opportunity_ID, body.Loss_Reason);
|
||||
return NextResponse.json({ success: true });
|
||||
|
||||
case 'account.priority':
|
||||
updateAccountPriority(body.Account_Name, body.Priority);
|
||||
return NextResponse.json({ success: true });
|
||||
|
||||
// Export
|
||||
case 'export': {
|
||||
const data = getDashboardData();
|
||||
|
||||
@@ -995,6 +995,10 @@ export function getSnapshotDates(): string[] {
|
||||
return (db.prepare('SELECT DISTINCT snapshot_date FROM pipeline_snapshots ORDER BY snapshot_date DESC').all() as { snapshot_date: string }[]).map(r => r.snapshot_date);
|
||||
}
|
||||
|
||||
export function updateAccountPriority(accountName: string, priority: string) {
|
||||
getDb().prepare('UPDATE accounts SET Priority = ? WHERE Account_Name = ?').run(priority, accountName);
|
||||
}
|
||||
|
||||
// --- Win/Loss helpers ---
|
||||
export function updateLossReason(opportunityId: string, lossReason: string) {
|
||||
getDb().prepare('UPDATE pipeline SET Loss_Reason = ? WHERE Opportunity_ID = ?').run(lossReason, opportunityId);
|
||||
|
||||
Reference in New Issue
Block a user