@@ -10,6 +10,7 @@ const PaymentsPage = () => {
1010 const navigate = useNavigate ( ) ;
1111 const [ transactions , setTransactions ] = useState ( [ ] ) ;
1212 const [ loading , setLoading ] = useState ( true ) ;
13+ const [ selectedTxns , setSelectedTxns ] = useState ( [ ] ) ;
1314
1415 useEffect ( ( ) => {
1516 loadTransactions ( ) ;
@@ -55,6 +56,47 @@ const PaymentsPage = () => {
5556 }
5657 } ;
5758
59+ const handleDelete = async ( txnId ) => {
60+ if ( confirm ( "Permanently purge this financial record from the ledger?" ) ) {
61+ try {
62+ await adminService . deleteDocument ( 'payments' , txnId ) ;
63+ loadTransactions ( ) ;
64+ } catch ( error ) {
65+ alert ( "Deletion failed" ) ;
66+ }
67+ }
68+ } ;
69+
70+ const handleBulkDelete = async ( ) => {
71+ if ( selectedTxns . length === 0 ) return ;
72+ if ( confirm ( `Execute mass purge of ${ selectedTxns . length } records? This cannot be undone.` ) ) {
73+ try {
74+ setLoading ( true ) ;
75+ await adminService . deletePayments ( selectedTxns ) ;
76+ setSelectedTxns ( [ ] ) ;
77+ await loadTransactions ( ) ;
78+ } catch ( error ) {
79+ alert ( "Bulk deletion failed" ) ;
80+ } finally {
81+ setLoading ( false ) ;
82+ }
83+ }
84+ } ;
85+
86+ const toggleSelection = ( id ) => {
87+ setSelectedTxns ( prev =>
88+ prev . includes ( id ) ? prev . filter ( item => item !== id ) : [ ...prev , id ]
89+ ) ;
90+ } ;
91+
92+ const toggleAll = ( ) => {
93+ if ( selectedTxns . length === transactions . length ) {
94+ setSelectedTxns ( [ ] ) ;
95+ } else {
96+ setSelectedTxns ( transactions . map ( t => t . id ) ) ;
97+ }
98+ } ;
99+
58100 if ( loading ) {
59101 return < Loading message = "Processing Ledger Data" /> ;
60102 }
@@ -72,6 +114,14 @@ const PaymentsPage = () => {
72114 </ h1 >
73115 </ div >
74116 < div className = "flex items-center gap-3" >
117+ { selectedTxns . length > 0 && (
118+ < button
119+ onClick = { handleBulkDelete }
120+ className = "flex items-center gap-2 px-5 py-2.5 bg-rose-600 text-white rounded-2xl text-xs font-black uppercase tracking-wider hover:bg-rose-700 transition-all active:scale-95 shadow-lg shadow-rose-500/20"
121+ >
122+ < Trash2 size = { 14 } /> Purge Selected ({ selectedTxns . length } )
123+ </ button >
124+ ) }
75125 < button className = "flex items-center gap-2 px-5 py-2.5 bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 text-slate-600 dark:text-white rounded-2xl text-xs font-black uppercase tracking-wider hover:bg-slate-50 transition-all" >
76126 < Filter size = { 14 } /> Filter
77127 </ button >
@@ -92,7 +142,15 @@ const PaymentsPage = () => {
92142 < table className = "w-full min-w-[2000px] border-collapse" >
93143 < thead >
94144 < tr className = "bg-slate-100 dark:bg-slate-900 font-black text-[10px] text-slate-500 dark:text-white uppercase tracking-widest text-left whitespace-nowrap" >
95- < th className = "px-4 py-3 border border-slate-200 dark:border-slate-800" > No</ th >
145+ < th className = "px-4 py-3 border border-slate-200 dark:border-slate-800 w-10 text-center" >
146+ < input
147+ type = "checkbox"
148+ checked = { selectedTxns . length === transactions . length && transactions . length > 0 }
149+ onChange = { toggleAll }
150+ className = "w-4 h-4 rounded-none border-slate-300 text-blue-600 focus:ring-blue-500"
151+ />
152+ </ th >
153+ < th className = "px-4 py-3 border border-slate-200 dark:border-slate-800 text-center" > No</ th >
96154 < th className = "px-4 py-3 border border-slate-200 dark:border-slate-800" > Business Name</ th >
97155 < th className = "px-4 py-3 border border-slate-200 dark:border-slate-800" > Business ID</ th >
98156 < th className = "px-4 py-3 border border-slate-200 dark:border-slate-800" > Owner Name</ th >
@@ -110,8 +168,16 @@ const PaymentsPage = () => {
110168 </ thead >
111169 < tbody className = "divide-y divide-slate-100 dark:divide-slate-900" >
112170 { transactions . map ( ( txn , index ) => (
113- < tr key = { txn . id } className = "group hover:bg-blue-50/50 dark:hover:bg-blue-900/20 transition-all duration-300 even:bg-slate-50/50 dark:even:bg-slate-900/10 whitespace-nowrap" >
114- < td className = "px-4 py-3 border border-slate-200 dark:border-slate-800" >
171+ < tr key = { txn . id } className = { `group hover:bg-blue-50/50 dark:hover:bg-blue-900/20 transition-all duration-300 ${ selectedTxns . includes ( txn . id ) ? 'bg-blue-50/30' : 'even:bg-slate-50/50 dark:even:bg-slate-900/10' } whitespace-nowrap` } >
172+ < td className = "px-4 py-3 border border-slate-200 dark:border-slate-800 text-center" >
173+ < input
174+ type = "checkbox"
175+ checked = { selectedTxns . includes ( txn . id ) }
176+ onChange = { ( ) => toggleSelection ( txn . id ) }
177+ className = "w-4 h-4 rounded-none border-slate-300 text-blue-600 focus:ring-blue-500"
178+ />
179+ </ td >
180+ < td className = "px-4 py-3 border border-slate-200 dark:border-slate-800 text-center" >
115181 < span className = "text-xs font-black text-slate-400 dark:text-white" > { String ( index + 1 ) . padStart ( 2 , '0' ) } </ span >
116182 </ td >
117183 < td className = "px-4 py-3 border border-slate-200 dark:border-slate-800" >
@@ -178,6 +244,13 @@ const PaymentsPage = () => {
178244 >
179245 < Eye size = { 12 } />
180246 </ button >
247+ < button
248+ onClick = { ( ) => handleDelete ( txn . id ) }
249+ className = "p-1.5 text-rose-600 bg-rose-50 dark:bg-rose-900/20 hover:bg-rose-600 hover:text-white transition-all border border-rose-100 dark:border-rose-800"
250+ title = "Purge Record"
251+ >
252+ < Trash2 size = { 12 } />
253+ </ button >
181254 { txn . status === 'pending' && (
182255 < >
183256 < button
0 commit comments