1- import React from "react" ;
1+ import React , { useMemo , useState } from "react" ;
22import { Transaction , PaymentStatus } from "../../types" ;
33import Card from "./Card" ;
44
@@ -7,10 +7,16 @@ interface TransactionHistoryProps {
77 loading ?: boolean ;
88}
99
10+ type DateFilter = "7d" | "30d" | "custom" | "all" ;
11+
1012const TransactionHistory : React . FC < TransactionHistoryProps > = ( {
1113 transactions,
1214 loading = false ,
1315} ) => {
16+ const [ dateFilter , setDateFilter ] = useState < DateFilter > ( "all" ) ;
17+ const [ customStart , setCustomStart ] = useState ( "" ) ;
18+ const [ customEnd , setCustomEnd ] = useState ( "" ) ;
19+
1420 const formatDate = ( dateString : string ) => {
1521 const date = new Date ( dateString ) ;
1622 return date . toLocaleDateString ( "en-IN" , {
@@ -34,6 +40,39 @@ const TransactionHistory: React.FC<TransactionHistoryProps> = ({
3440 ) ;
3541 } ;
3642
43+ const filteredTransactions = useMemo ( ( ) => {
44+ if ( dateFilter === "all" ) return transactions ;
45+
46+ const now = new Date ( ) ;
47+ const nowAtMidnight = new Date ( now . getFullYear ( ) , now . getMonth ( ) , now . getDate ( ) ) . getTime ( ) ;
48+
49+ return transactions . filter ( ( transaction ) => {
50+ const txDate = new Date ( transaction . created_at ) ;
51+ const txAtMidnight = new Date ( txDate . getFullYear ( ) , txDate . getMonth ( ) , txDate . getDate ( ) ) . getTime ( ) ;
52+
53+ if ( dateFilter === "7d" ) {
54+ const sevenDaysAgo = nowAtMidnight - 6 * 24 * 60 * 60 * 1000 ;
55+ return txAtMidnight >= sevenDaysAgo && txAtMidnight <= nowAtMidnight ;
56+ }
57+
58+ if ( dateFilter === "30d" ) {
59+ const thirtyDaysAgo = nowAtMidnight - 29 * 24 * 60 * 60 * 1000 ;
60+ return txAtMidnight >= thirtyDaysAgo && txAtMidnight <= nowAtMidnight ;
61+ }
62+
63+ if ( dateFilter === "custom" ) {
64+ if ( ! customStart || ! customEnd ) return true ;
65+ const start = new Date ( `${ customStart } T00:00:00` ) . getTime ( ) ;
66+ const end = new Date ( `${ customEnd } T23:59:59` ) . getTime ( ) ;
67+ return txDate . getTime ( ) >= start && txDate . getTime ( ) <= end ;
68+ }
69+
70+ return true ;
71+ } ) ;
72+ } , [ transactions , dateFilter , customStart , customEnd ] ) ;
73+
74+ const showEmptyFiltered = transactions . length > 0 && filteredTransactions . length === 0 ;
75+
3776 if ( loading ) {
3877 return (
3978 < Card className = "p-4 md:p-6" >
@@ -47,13 +86,40 @@ const TransactionHistory: React.FC<TransactionHistoryProps> = ({
4786
4887 return (
4988 < Card className = "p-4 md:p-6" >
50- < h2 className = "text-lg md:text-xl font-semibold mb-4" >
51- Transaction History
52- </ h2 >
89+ < div className = "flex flex-col md:flex-row md:items-center md:justify-between gap-3 mb-4" >
90+ < h2 className = "text-lg md:text-xl font-semibold" >
91+ Transaction History
92+ </ h2 >
93+ < div className = "flex flex-wrap items-center gap-2" >
94+ < button onClick = { ( ) => setDateFilter ( "7d" ) } className = { `px-3 py-1 text-xs rounded-md border ${ dateFilter === "7d" ? "bg-zinc-700 border-zinc-600 text-white" : "border-zinc-700 text-zinc-300 hover:bg-zinc-800" } ` } > Last 7 days</ button >
95+ < button onClick = { ( ) => setDateFilter ( "30d" ) } className = { `px-3 py-1 text-xs rounded-md border ${ dateFilter === "30d" ? "bg-zinc-700 border-zinc-600 text-white" : "border-zinc-700 text-zinc-300 hover:bg-zinc-800" } ` } > Last 30 days</ button >
96+ < button onClick = { ( ) => setDateFilter ( "custom" ) } className = { `px-3 py-1 text-xs rounded-md border ${ dateFilter === "custom" ? "bg-zinc-700 border-zinc-600 text-white" : "border-zinc-700 text-zinc-300 hover:bg-zinc-800" } ` } > Custom</ button >
97+ < button onClick = { ( ) => setDateFilter ( "all" ) } className = { `px-3 py-1 text-xs rounded-md border ${ dateFilter === "all" ? "bg-zinc-700 border-zinc-600 text-white" : "border-zinc-700 text-zinc-300 hover:bg-zinc-800" } ` } > All</ button >
98+ </ div >
99+ </ div >
100+
101+ { dateFilter === "custom" && (
102+ < div className = "grid grid-cols-1 sm:grid-cols-2 gap-3 mb-4" >
103+ < input
104+ type = "date"
105+ value = { customStart }
106+ onChange = { ( e ) => setCustomStart ( e . target . value ) }
107+ className = "w-full px-3 py-2 bg-zinc-800 border border-zinc-700 rounded-md text-white"
108+ aria-label = "Custom start date"
109+ />
110+ < input
111+ type = "date"
112+ value = { customEnd }
113+ onChange = { ( e ) => setCustomEnd ( e . target . value ) }
114+ className = "w-full px-3 py-2 bg-zinc-800 border border-zinc-700 rounded-md text-white"
115+ aria-label = "Custom end date"
116+ />
117+ </ div >
118+ ) }
53119
54- { transactions . length === 0 ? (
120+ { filteredTransactions . length === 0 ? (
55121 < p className = "text-sm text-gray-400 text-center py-8" >
56- No transactions found.
122+ { showEmptyFiltered ? " No transactions found for the selected date range." : "No transactions found." }
57123 </ p >
58124 ) : (
59125 < div className = "overflow-x-auto" >
@@ -75,7 +141,7 @@ const TransactionHistory: React.FC<TransactionHistoryProps> = ({
75141 </ tr >
76142 </ thead >
77143 < tbody >
78- { transactions . map ( ( transaction ) => (
144+ { filteredTransactions . map ( ( transaction ) => (
79145 < tr
80146 key = { transaction . id }
81147 className = "border-b border-white/5 hover:bg-white/5 transition-colors"
0 commit comments