Skip to content

Commit a0d3bc4

Browse files
committed
reports page
1 parent 623fe17 commit a0d3bc4

File tree

2 files changed

+294
-97
lines changed

2 files changed

+294
-97
lines changed

src/app/reports/page.tsx

Lines changed: 102 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
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";
1111
import { parseUnits } from "viem";
1212
import { useReadContract } from "wagmi";
@@ -15,6 +15,32 @@ import { useRewardTypes, useProgramCodeToId } from "@/hooks/useRewardsProgram";
1515
import { useChunkedEventLogs, type TimeRange } from "@/hooks/useChunkedEventLogs";
1616
import { 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+
1844
export 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

Comments
 (0)