From 5c9e70da202a25a3246f0f53272f4392f21f83d6 Mon Sep 17 00:00:00 2001 From: saridsa2 Date: Thu, 16 Apr 2026 17:20:54 +0530 Subject: [PATCH] =?UTF-8?q?fix:=20Leads=20page=20cleanup=20=E2=80=94=20rem?= =?UTF-8?q?ove=20tabs,=20checkboxes,=20inline=20header?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove New/My Leads/All Leads tabs — redundant now that contacts are on a separate page; all leads shown as a flat list - Remove row checkboxes (selectionMode="none") — bulk actions weren't wired to any backend and confused QA - Move Search + Columns + Export into the header row alongside the title — cleaner single-row layout - Remove BulkActionBar + AssignModal + WhatsAppSendModal + MarkSpamModal imports and JSX — dead code without checkboxes - LeadTable: new selectionMode prop (default "multiple" for back-compat) - Same cleanup on Contacts page (no checkboxes) Co-Authored-By: Claude Opus 4.6 (1M context) --- .claude/settings.local.json | 16 +++ src/components/leads/lead-table.tsx | 4 +- src/pages/all-leads.tsx | 187 ++++++++-------------------- src/pages/contacts.tsx | 8 +- 4 files changed, 72 insertions(+), 143 deletions(-) create mode 100644 .claude/settings.local.json diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..20c4ba8 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,16 @@ +{ + "permissions": { + "allow": [ + "Bash(ps -eo pid,pcpu,rss,comm -r)", + "Bash(awk 'NR<=20{printf \"%-8s %-8s %-10s %s\\\\n\", $1, $2, $3/1024 \"MB\", $4}')", + "Bash(top -l 1 -o cpu -n 15 -stats pid,command,cpu,mem,th)", + "Bash(vm_stat)", + "Bash(sysctl hw.memsize)", + "Bash(awk '{print \"Total RAM: \" $2/1024/1024/1024 \" GB\"}')", + "Bash(ps aux:*)", + "Bash(pmset -g thermlog)", + "Bash(sudo powermetrics:*)", + "Bash(sysctl machdep.xcpm.cpu_thermal_level)" + ] + } +} diff --git a/src/components/leads/lead-table.tsx b/src/components/leads/lead-table.tsx index d34c1ce..00f2b0b 100644 --- a/src/components/leads/lead-table.tsx +++ b/src/components/leads/lead-table.tsx @@ -25,6 +25,7 @@ type LeadTableProps = { onSort: (field: string) => void; onViewActivity?: (lead: Lead) => void; visibleColumns?: Set; + selectionMode?: 'multiple' | 'none'; }; type TableRow = { @@ -55,6 +56,7 @@ export const LeadTable = ({ onSort, onViewActivity, visibleColumns, + selectionMode, }: LeadTableProps) => { const [expandedDupId, setExpandedDupId] = useState(null); @@ -118,7 +120,7 @@ export const LeadTable = ({
= ({ className }) => = ({ className }) => ; import { Button } from '@/components/base/buttons/button'; import { Input } from '@/components/base/input/input'; -import { Tabs, TabList, Tab } from '@/components/application/tabs/tabs'; +// Tabs removed — campaign pills handle all filtering now +// import { Tabs, TabList, Tab } from '@/components/application/tabs/tabs'; import { PaginationPageDefault } from '@/components/application/pagination/pagination'; -import { TopBar } from '@/components/layout/top-bar'; +// TopBar replaced by inline header +// import { TopBar } from '@/components/layout/top-bar'; import { LeadTable } from '@/components/leads/lead-table'; import { ColumnToggle, useColumnVisibility } from '@/components/application/table/column-toggle'; -import { BulkActionBar } from '@/components/leads/bulk-action-bar'; +// Bulk actions removed — checkboxes hidden +// import { BulkActionBar } from '@/components/leads/bulk-action-bar'; import { FilterPills } from '@/components/leads/filter-pills'; -import { AssignModal } from '@/components/modals/assign-modal'; -import { WhatsAppSendModal } from '@/components/modals/whatsapp-send-modal'; -import { MarkSpamModal } from '@/components/modals/mark-spam-modal'; +// Bulk action modals removed — checkboxes hidden +// import { AssignModal } from '@/components/modals/assign-modal'; +// import { WhatsAppSendModal } from '@/components/modals/whatsapp-send-modal'; +// import { MarkSpamModal } from '@/components/modals/mark-spam-modal'; import { LeadActivitySlideout } from '@/components/leads/lead-activity-slideout'; import { useLeads } from '@/hooks/use-leads'; import { useAuth } from '@/providers/auth-provider'; @@ -41,29 +45,28 @@ export const AllLeadsPage = () => { const { user } = useAuth(); const [searchParams] = useSearchParams(); const initialSource = searchParams.get('source') as LeadSource | null; - const [tab, setTab] = useState('new'); - const [selectedIds, setSelectedIds] = useState([]); + const tab: TabKey = 'all'; // Tabs removed — show all campaign-sourced leads const [sortField, setSortField] = useState('createdAt'); const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>('desc'); const [sourceFilter, setSourceFilter] = useState(initialSource); const [searchQuery, setSearchQuery] = useState(''); const [currentPage, setCurrentPage] = useState(1); - const statusFilter: LeadStatus | undefined = tab === 'new' ? 'NEW' : undefined; - const myLeadsOnly = tab === 'my-leads'; + const statusFilter: LeadStatus | undefined = undefined; + const myLeadsOnly = false; // Exclude organic contact sources — those live on the Contacts page. // Leads page shows campaign-sourced / marketing-qualified leads only. const CONTACT_SOURCES = useMemo(() => new Set(['PHONE', 'WALK_IN', 'REFERRAL'] as const), []); - const { leads: filteredLeads, total, updateLead } = useLeads({ + const { leads: filteredLeads, total } = useLeads({ source: sourceFilter ?? undefined, excludeSources: CONTACT_SOURCES, status: statusFilter, search: searchQuery || undefined, }); - const { agents, templates, leadActivities, campaigns } = useData(); + const { leadActivities, campaigns } = useData(); const [campaignFilter, setCampaignFilter] = useState(null); const columnDefs = [ @@ -165,11 +168,6 @@ export const AllLeadsPage = () => { setCurrentPage(1); }; - const handleTabChange = (key: string | number) => { - setTab(key as TabKey); - setCurrentPage(1); - setSelectedIds([]); - }; const handleExportCsv = () => { // Export exactly what the user currently sees — same filters, same @@ -211,7 +209,6 @@ export const AllLeadsPage = () => { const handlePageChange = (page: number) => { setCurrentPage(page); - setSelectedIds([]); }; // Build active filters for pills display @@ -235,27 +232,6 @@ export const AllLeadsPage = () => { setCurrentPage(1); }; - const myLeadsCount = sortedLeads.filter((l) => l.assignedAgent === user.name).length; - - const tabItems = [ - { id: 'new', label: 'New', badge: tab === 'new' ? total : undefined }, - { id: 'my-leads', label: 'My Leads', badge: tab === 'my-leads' ? myLeadsCount : undefined }, - { id: 'all', label: 'All Leads', badge: tab === 'all' ? total : undefined }, - ]; - - // Bulk action modal state - const [isAssignOpen, setIsAssignOpen] = useState(false); - const [isWhatsAppOpen, setIsWhatsAppOpen] = useState(false); - const [isSpamOpen, setIsSpamOpen] = useState(false); - - const selectedLeadsForAction = useMemo( - () => displayLeads.filter((l) => selectedIds.includes(l.id)), - [displayLeads, selectedIds], - ); - - const handleBulkAssign = () => setIsAssignOpen(true); - const handleBulkWhatsApp = () => setIsWhatsAppOpen(true); - const handleBulkSpam = () => setIsSpamOpen(true); // Activity slideout state const [activityLead, setActivityLead] = useState(null); @@ -268,46 +244,39 @@ export const AllLeadsPage = () => { return (
- + {/* Header with controls inline */} +
+
+

All Leads

+

{total} total

+
+
+
+ { + setSearchQuery(value); + setCurrentPage(1); + }} + aria-label="Search leads" + /> +
+ + +
+
- {/* Tabs + Controls row */} -
-
- - - {(item) => ( - - )} - - -
- -
-
- { - setSearchQuery(value); - setCurrentPage(1); - }} - aria-label="Search leads" - /> -
- - -
-
{/* Active filters */} {activeFilters.length > 0 && ( @@ -366,25 +335,13 @@ export const AllLeadsPage = () => {
)} - {/* Bulk action bar */} - {selectedIds.length > 0 && ( -
- setSelectedIds([])} - /> -
- )} - {/* Table — fills remaining space, scrolls internally */}
{}} + selectedIds={[]} + selectionMode="none" sortField={sortField} sortDirection={sortDirection} onSort={handleSort} @@ -405,52 +362,6 @@ export const AllLeadsPage = () => { )}
- {/* Bulk action modals */} - {selectedLeadsForAction.length > 0 && ( - <> - { - const agentName = agents.find((a) => a.id === agentId)?.name ?? null; - selectedIds.forEach((id) => { - updateLead(id, { assignedAgent: agentName, leadStatus: 'CONTACTED' }); - }); - setIsAssignOpen(false); - setSelectedIds([]); - }} - /> - t.approvalStatus === 'APPROVED')} - onSend={() => { - setIsWhatsAppOpen(false); - setSelectedIds([]); - }} - /> - - )} - - {/* Bulk spam: use first selected lead for the single-lead MarkSpamModal */} - {selectedLeadsForAction.length > 0 && selectedLeadsForAction[0] && ( - { - selectedIds.forEach((id) => { - updateLead(id, { isSpam: true, leadStatus: 'LOST' }); - }); - setIsSpamOpen(false); - setSelectedIds([]); - }} - /> - )} - {/* Activity slideout */} {activityLead && ( { const { leads, leadActivities } = useData(); const [searchQuery, setSearchQuery] = useState(''); const [currentPage, setCurrentPage] = useState(1); - const [selectedIds, setSelectedIds] = useState([]); const [sortField, setSortField] = useState('createdAt'); const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>('desc'); const [activityLead, setActivityLead] = useState(null); @@ -142,8 +141,9 @@ export const ContactsPage = () => {
{}} + selectionMode="none" sortField={sortField} sortDirection={sortDirection} onSort={handleSort} @@ -157,7 +157,7 @@ export const ContactsPage = () => { { setCurrentPage(page); setSelectedIds([]); }} + onPageChange={(page) => { setCurrentPage(page); }} />
)}