66 TableContainer , TableHead , TableRow , TextField , Button ,
77 Select , MenuItem , FormControl , InputLabel , Alert , Chip ,
88 LinearProgress , TablePagination , useMediaQuery , useTheme ,
9- InputAdornment ,
9+ InputAdornment , ListSubheader ,
1010} from "@mui/material" ;
1111import { parseUnits } from "viem" ;
1212import { useReadContract } from "wagmi" ;
@@ -15,6 +15,32 @@ import { useRewardTypes, useProgramCodeToId } from "@/hooks/useRewardsProgram";
1515import { useChunkedEventLogs , type TimeRange } from "@/hooks/useChunkedEventLogs" ;
1616import { formatFula , shortenAddress , fromBytes16 , toBytes12 } from "@/lib/utils" ;
1717
18+ // Event type → chip color
19+ type ChipColor = "success" | "info" | "warning" | "secondary" | "primary" | "default" | "error" ;
20+ const EVENT_CHIP_COLOR : Record < string , ChipColor > = {
21+ Deposit : "success" , Transfer : "info" , TransferToParent : "info" , Withdrawal : "warning" , TimeLockResolved : "warning" ,
22+ MemberAdded : "secondary" , PAAssigned : "secondary" , MemberRemoved : "error" , MemberClaimed : "secondary" ,
23+ WalletChanged : "secondary" , MemberIDUpdated : "secondary" , TypeChanged : "secondary" ,
24+ ProgramCreated : "primary" , ProgramUpdated : "primary" , ProgramDeactivated : "error" , LimitUpdated : "primary" ,
25+ RewardTypeAdded : "default" , RewardTypeRemoved : "default" , SubTypeAdded : "default" , SubTypeRemoved : "default" ,
26+ } ;
27+
28+ // Friendly labels for the filter dropdown
29+ const EVENT_LABELS : Record < string , string > = {
30+ Deposit : "Deposit" , Transfer : "Transfer to Member" , TransferToParent : "Transfer to Parent" ,
31+ Withdrawal : "Withdrawal" , TimeLockResolved : "Time Lock Resolved" ,
32+ MemberAdded : "Member Added" , PAAssigned : "PA Assigned" , MemberRemoved : "Member Removed" ,
33+ MemberClaimed : "Member Claimed" , WalletChanged : "Wallet Changed" ,
34+ MemberIDUpdated : "Member ID Updated" , TypeChanged : "Member Type Changed" ,
35+ ProgramCreated : "Program Created" , ProgramUpdated : "Program Updated" ,
36+ ProgramDeactivated : "Program Deactivated" , LimitUpdated : "Transfer Limit Updated" ,
37+ RewardTypeAdded : "Reward Type Added" , RewardTypeRemoved : "Reward Type Removed" ,
38+ SubTypeAdded : "Sub-Type Added" , SubTypeRemoved : "Sub-Type Removed" ,
39+ } ;
40+
41+ // Token events have amounts
42+ const TOKEN_EVENTS = new Set ( [ "Deposit" , "Transfer" , "TransferToParent" , "Withdrawal" , "TimeLockResolved" ] ) ;
43+
1844export default function ReportsPage ( ) {
1945 const theme = useTheme ( ) ;
2046 const isMobile = useMediaQuery ( theme . breakpoints . down ( "sm" ) ) ;
@@ -36,7 +62,7 @@ export default function ReportsPage() {
3662 const [ filterAmountMin , setFilterAmountMin ] = useState ( "" ) ;
3763 const [ filterAmountMax , setFilterAmountMax ] = useState ( "" ) ;
3864
39- // Resolve member ID → storage key for filtering
65+ // Resolve member ID -> storage key for filtering
4066 const filterMemberIDBytes = filterMemberID . length > 0 ? toBytes12 ( filterMemberID ) : undefined ;
4167 const { data : filterMemberKey } = useReadContract ( {
4268 address : CONTRACTS . rewardsProgram ,
@@ -88,6 +114,8 @@ export default function ReportsPage() {
88114 const totalDeposits = filteredEvents . filter ( e => e . type === "Deposit" ) . reduce ( ( s , e ) => s + e . amount , BigInt ( 0 ) ) ;
89115 const totalTransfers = filteredEvents . filter ( e => e . type === "Transfer" || e . type === "TransferToParent" ) . reduce ( ( s , e ) => s + e . amount , BigInt ( 0 ) ) ;
90116 const totalWithdrawals = filteredEvents . filter ( e => e . type === "Withdrawal" ) . reduce ( ( s , e ) => s + e . amount , BigInt ( 0 ) ) ;
117+ const memberEventCount = filteredEvents . filter ( e => [ "MemberAdded" , "PAAssigned" , "MemberRemoved" , "MemberClaimed" , "WalletChanged" , "MemberIDUpdated" , "TypeChanged" ] . includes ( e . type ) ) . length ;
118+ const adminEventCount = filteredEvents . filter ( e => [ "ProgramCreated" , "ProgramUpdated" , "ProgramDeactivated" , "LimitUpdated" , "RewardTypeAdded" , "RewardTypeRemoved" , "SubTypeAdded" , "SubTypeRemoved" ] . includes ( e . type ) ) . length ;
91119
92120 const rewardTypeNames : Record < number , string > = { } ;
93121 if ( rewardTypesData ) {
@@ -106,7 +134,6 @@ export default function ReportsPage() {
106134 }
107135 } ;
108136
109- // Pagination — clamp page if filters reduce result count
110137 const safePage = page * rowsPerPage >= filteredEvents . length && filteredEvents . length > 0 ? 0 : page ;
111138 const paginatedEvents = filteredEvents . slice (
112139 safePage * rowsPerPage ,
@@ -165,10 +192,29 @@ export default function ReportsPage() {
165192 < InputLabel > Event Type</ InputLabel >
166193 < Select value = { filterEventType } onChange = { ( e ) => { setFilterEventType ( e . target . value ) ; setPage ( 0 ) ; } } label = "Event Type" >
167194 < MenuItem value = "" > All</ MenuItem >
195+ < ListSubheader > Token Events</ ListSubheader >
168196 < MenuItem value = "Deposit" > Deposit</ MenuItem >
169- < MenuItem value = "Transfer" > Transfer</ MenuItem >
170- < MenuItem value = "TransferToParent" > To Parent</ MenuItem >
197+ < MenuItem value = "Transfer" > Transfer to Member </ MenuItem >
198+ < MenuItem value = "TransferToParent" > Transfer to Parent</ MenuItem >
171199 < MenuItem value = "Withdrawal" > Withdrawal</ MenuItem >
200+ < MenuItem value = "TimeLockResolved" > Time Lock Resolved</ MenuItem >
201+ < ListSubheader > Member Events</ ListSubheader >
202+ < MenuItem value = "MemberAdded" > Member Added</ MenuItem >
203+ < MenuItem value = "PAAssigned" > PA Assigned</ MenuItem >
204+ < MenuItem value = "MemberRemoved" > Member Removed</ MenuItem >
205+ < MenuItem value = "MemberClaimed" > Member Claimed</ MenuItem >
206+ < MenuItem value = "WalletChanged" > Wallet Changed</ MenuItem >
207+ < MenuItem value = "MemberIDUpdated" > Member ID Updated</ MenuItem >
208+ < MenuItem value = "TypeChanged" > Member Type Changed</ MenuItem >
209+ < ListSubheader > Program / Admin</ ListSubheader >
210+ < MenuItem value = "ProgramCreated" > Program Created</ MenuItem >
211+ < MenuItem value = "ProgramUpdated" > Program Updated</ MenuItem >
212+ < MenuItem value = "ProgramDeactivated" > Program Deactivated</ MenuItem >
213+ < MenuItem value = "LimitUpdated" > Transfer Limit Updated</ MenuItem >
214+ < MenuItem value = "RewardTypeAdded" > Reward Type Added</ MenuItem >
215+ < MenuItem value = "RewardTypeRemoved" > Reward Type Removed</ MenuItem >
216+ < MenuItem value = "SubTypeAdded" > Sub-Type Added</ MenuItem >
217+ < MenuItem value = "SubTypeRemoved" > Sub-Type Removed</ MenuItem >
172218 </ Select >
173219 </ FormControl >
174220 </ Grid >
@@ -228,30 +274,48 @@ export default function ReportsPage() {
228274 { filteredEvents . length > 0 && (
229275 < >
230276 < Grid container spacing = { 2 } sx = { { mb : 3 } } >
231- < Grid item xs = { 12 } sm = { 4 } >
277+ < Grid item xs = { 6 } sm = { 2.4 } >
278+ < Paper sx = { { p : 2 , textAlign : "center" } } >
279+ < Typography color = "text.secondary" variant = "body2" > Deposits</ Typography >
280+ < Typography variant = "h6" color = "success.main" > { formatFula ( totalDeposits ) } </ Typography >
281+ < Typography variant = "caption" color = "text.secondary" >
282+ { filteredEvents . filter ( e => e . type === "Deposit" ) . length } txns
283+ </ Typography >
284+ </ Paper >
285+ </ Grid >
286+ < Grid item xs = { 6 } sm = { 2.4 } >
232287 < Paper sx = { { p : 2 , textAlign : "center" } } >
233- < Typography color = "text.secondary" variant = "body2" > Total Deposits </ Typography >
234- < Typography variant = "h6" color = "success .main" > { formatFula ( totalDeposits ) } FULA </ Typography >
288+ < Typography color = "text.secondary" variant = "body2" > Transfers </ Typography >
289+ < Typography variant = "h6" color = "info .main" > { formatFula ( totalTransfers ) } </ Typography >
235290 < Typography variant = "caption" color = "text.secondary" >
236- { filteredEvents . filter ( e => e . type === "Deposit" ) . length } transactions
291+ { filteredEvents . filter ( e => e . type === "Transfer" || e . type === "TransferToParent" ) . length } txns
237292 </ Typography >
238293 </ Paper >
239294 </ Grid >
240- < Grid item xs = { 12 } sm = { 4 } >
295+ < Grid item xs = { 6 } sm = { 2. 4} >
241296 < Paper sx = { { p : 2 , textAlign : "center" } } >
242- < Typography color = "text.secondary" variant = "body2" > Total Transfers </ Typography >
243- < Typography variant = "h6" color = "info .main" > { formatFula ( totalTransfers ) } FULA </ Typography >
297+ < Typography color = "text.secondary" variant = "body2" > Withdrawals </ Typography >
298+ < Typography variant = "h6" color = "warning .main" > { formatFula ( totalWithdrawals ) } </ Typography >
244299 < Typography variant = "caption" color = "text.secondary" >
245- { filteredEvents . filter ( e => e . type === "Transfer" || e . type === "TransferToParent" ) . length } transactions
300+ { filteredEvents . filter ( e => e . type === "Withdrawal" ) . length } txns
246301 </ Typography >
247302 </ Paper >
248303 </ Grid >
249- < Grid item xs = { 12 } sm = { 4 } >
304+ < Grid item xs = { 6 } sm = { 2. 4} >
250305 < Paper sx = { { p : 2 , textAlign : "center" } } >
251- < Typography color = "text.secondary" variant = "body2" > Total Withdrawals </ Typography >
252- < Typography variant = "h6" color = "warning .main" > { formatFula ( totalWithdrawals ) } FULA </ Typography >
306+ < Typography color = "text.secondary" variant = "body2" > Member Events </ Typography >
307+ < Typography variant = "h6" color = "secondary .main" > { memberEventCount } </ Typography >
253308 < Typography variant = "caption" color = "text.secondary" >
254- { filteredEvents . filter ( e => e . type === "Withdrawal" ) . length } transactions
309+ added / claimed / changed
310+ </ Typography >
311+ </ Paper >
312+ </ Grid >
313+ < Grid item xs = { 12 } sm = { 2.4 } >
314+ < Paper sx = { { p : 2 , textAlign : "center" } } >
315+ < Typography color = "text.secondary" variant = "body2" > Admin Events</ Typography >
316+ < Typography variant = "h6" color = "primary.main" > { adminEventCount } </ Typography >
317+ < Typography variant = "caption" color = "text.secondary" >
318+ programs / types / limits
255319 </ Typography >
256320 </ Paper >
257321 </ Grid >
@@ -264,8 +328,8 @@ export default function ReportsPage() {
264328 < TableCell > Type</ TableCell >
265329 < TableCell > Program</ TableCell >
266330 < TableCell > Wallet</ TableCell >
267- < TableCell > Amount (FULA) </ TableCell >
268- < TableCell > Reward Type</ TableCell >
331+ < TableCell > Amount / Detail </ TableCell >
332+ { ! isMobile && < TableCell > Reward Type</ TableCell > }
269333 { ! isMobile && < TableCell > Note</ TableCell > }
270334 { ! isMobile && < TableCell > Block</ TableCell > }
271335 </ TableRow >
@@ -275,19 +339,33 @@ export default function ReportsPage() {
275339 < TableRow key = { `${ row . txHash } -${ i } ` } hover >
276340 < TableCell >
277341 < Chip
278- label = { row . type }
342+ label = { EVENT_LABELS [ row . type ] || row . type }
279343 size = "small"
280- color = { row . type === "Deposit" ? "success" : row . type === "Withdrawal" ? "warning" : "info "}
344+ color = { EVENT_CHIP_COLOR [ row . type ] || "default "}
281345 />
282346 </ TableCell >
283347 < TableCell > { row . programId } </ TableCell >
284348 < TableCell sx = { { fontFamily : "monospace" , fontSize : "0.85rem" } } >
285- { shortenAddress ( row . wallet ) }
349+ { row . wallet ? shortenAddress ( row . wallet ) : "-" }
286350 </ TableCell >
287- < TableCell > { formatFula ( row . amount ) } </ TableCell >
288351 < TableCell >
289- { row . rewardType !== undefined ? ( rewardTypeNames [ row . rewardType ] || row . rewardType ) : "-" }
352+ { TOKEN_EVENTS . has ( row . type ) && row . amount > BigInt ( 0 )
353+ ? formatFula ( row . amount )
354+ : "" }
355+ { row . detail && (
356+ < Typography variant = "caption" color = "text.secondary" component = "div"
357+ sx = { { maxWidth : 220 , overflow : "hidden" , textOverflow : "ellipsis" , whiteSpace : "nowrap" } } >
358+ { row . detail }
359+ </ Typography >
360+ ) }
290361 </ TableCell >
362+ { ! isMobile && (
363+ < TableCell >
364+ { row . rewardType !== undefined && row . rewardType > 0
365+ ? ( rewardTypeNames [ row . rewardType ] || row . rewardType )
366+ : "-" }
367+ </ TableCell >
368+ ) }
291369 { ! isMobile && (
292370 < TableCell sx = { { maxWidth : 200 , overflow : "hidden" , textOverflow : "ellipsis" , whiteSpace : "nowrap" } } >
293371 { row . note || "-" }
0 commit comments