From 1e0845c4beaacc74115e5f82f95d2c5c3f4748b7 Mon Sep 17 00:00:00 2001 From: CycroftX Date: Tue, 3 Feb 2026 20:47:08 +0530 Subject: [PATCH] Enhance Events page with column sorting and filtering --- src/pages/Events.tsx | 174 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 150 insertions(+), 24 deletions(-) diff --git a/src/pages/Events.tsx b/src/pages/Events.tsx index 1f64c72..845f057 100644 --- a/src/pages/Events.tsx +++ b/src/pages/Events.tsx @@ -1,6 +1,8 @@ -import { Calendar, Ticket, Flag, Search, Filter, Plus, ArrowUpDown } from 'lucide-react'; +import { useState, useMemo } from 'react'; +import { Calendar, Ticket, Flag, Search, Filter, Plus, ArrowUpDown, ArrowUp, ArrowDown, Check } from 'lucide-react'; import { DropdownMenu, + DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, @@ -21,7 +23,71 @@ const statusStyles = { flagged: 'bg-error/10 text-error', }; +type SortKey = 'title' | 'partnerName' | 'date' | 'status' | 'ticketsSold' | 'revenue'; + export default function Events() { + const [searchQuery, setSearchQuery] = useState(''); + const [sortConfig, setSortConfig] = useState<{ key: SortKey; direction: 'asc' | 'desc' } | null>(null); + const [statusFilters, setStatusFilters] = useState([]); + + const allStatuses = ['draft', 'published', 'live', 'completed', 'cancelled', 'flagged']; + + const filteredAndSortedEvents = useMemo(() => { + let result = [...mockEvents]; + + // Filter by Search + if (searchQuery) { + const lowerQuery = searchQuery.toLowerCase(); + result = result.filter(event => + event.title.toLowerCase().includes(lowerQuery) || + event.partnerName.toLowerCase().includes(lowerQuery) + ); + } + + // Filter by Status + if (statusFilters.length > 0) { + result = result.filter(event => statusFilters.includes(event.status)); + } + + // Sort + if (sortConfig) { + result.sort((a, b) => { + const aValue = a[sortConfig.key]; + const bValue = b[sortConfig.key]; + + if (aValue < bValue) return sortConfig.direction === 'asc' ? -1 : 1; + if (aValue > bValue) return sortConfig.direction === 'asc' ? 1 : -1; + return 0; + }); + } + + return result; + }, [mockEvents, searchQuery, statusFilters, sortConfig]); + + const handleSort = (key: SortKey) => { + setSortConfig(current => { + if (current?.key === key) { + return { key, direction: current.direction === 'asc' ? 'desc' : 'asc' }; + } + return { key, direction: 'asc' }; + }); + }; + + const toggleStatusFilter = (status: string) => { + setStatusFilters(current => + current.includes(status) + ? current.filter(s => s !== status) + : [...current, status] + ); + }; + + const SortIcon = ({ column }: { column: SortKey }) => { + if (sortConfig?.key !== column) return ; + return sortConfig.direction === 'asc' + ? + : ; + }; + return (
-

43

+

+ {mockEvents.filter(e => e.status === 'live').length} +

Live Events

@@ -57,7 +125,9 @@ export default function Events() {
-

3

+

+ {mockEvents.filter(e => e.status === 'flagged').length} +

Flagged Events

@@ -74,32 +144,51 @@ export default function Events() { setSearchQuery(e.target.value)} className="h-10 w-64 pl-10 pr-4 rounded-xl text-sm bg-secondary shadow-neu-inset focus:outline-none focus:ring-2 focus:ring-accent/50" /> - - - Sort by + + Filter by Status - Newest First - Oldest First - Name (A-Z) - Upcoming - Status + {allStatuses.map(status => ( + toggleStatusFilter(status)} + className="capitalize" + > + {status} + + ))} + {statusFilters.length > 0 && ( + <> + + setStatusFilters([])} + > + Clear Filters + + + )} -