191 lines
5.9 KiB
TypeScript
191 lines
5.9 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useState } from "react";
|
|
import {
|
|
Box,
|
|
Button,
|
|
IconButton,
|
|
Paper,
|
|
Table,
|
|
TableBody,
|
|
TableCell,
|
|
TableContainer,
|
|
TableHead,
|
|
TableRow,
|
|
Typography,
|
|
} from "@mui/material";
|
|
import CheckCircleIcon from "@mui/icons-material/CheckCircle";
|
|
import CancelIcon from "@mui/icons-material/Cancel";
|
|
import MoreVertIcon from "@mui/icons-material/MoreVert";
|
|
|
|
import { dashboardService } from "@/app/services/dashboardService";
|
|
import { formatToDateTimeString } from "@/app/utils/formatDate";
|
|
|
|
import "./TransactionsWaitingApproval.scss";
|
|
import {
|
|
type IReviewTransactionsData,
|
|
type IReviewTransaction,
|
|
} from "@/app/services/types";
|
|
import StatusChangeDialog from "../DataTable/StatusChangeDialog";
|
|
|
|
interface ITransactionsWaitingApprovalProps {
|
|
initialReviewTransactions?: IReviewTransactionsData | null;
|
|
}
|
|
|
|
export const TransactionsWaitingApproval = ({
|
|
initialReviewTransactions = null,
|
|
}: ITransactionsWaitingApprovalProps) => {
|
|
const [reviewTransactions, setReviewTransactions] =
|
|
useState<IReviewTransactionsData | null>(
|
|
initialReviewTransactions ||
|
|
dashboardService.getCurrentDashboardData()?.reviewTransactions ||
|
|
null
|
|
);
|
|
const [statusDialogData, setStatusDialogData] = useState<{
|
|
rowId: number;
|
|
newStatus: string;
|
|
} | null>(null);
|
|
|
|
/**
|
|
* Subscribe to dashboard data changes
|
|
*/
|
|
useEffect(() => {
|
|
const subscription = dashboardService
|
|
.getDashboardData$()
|
|
.subscribe(data => {
|
|
if (data?.reviewTransactions) {
|
|
setReviewTransactions(data.reviewTransactions);
|
|
}
|
|
});
|
|
|
|
// Cleanup subscription on unmount
|
|
return () => subscription.unsubscribe();
|
|
}, []);
|
|
|
|
/**
|
|
* Format transaction for display
|
|
*/
|
|
const formatTransaction = (tx: IReviewTransaction) => {
|
|
const createdDate = tx.created || tx.modified || "";
|
|
const formattedDate = createdDate
|
|
? formatToDateTimeString(createdDate)
|
|
: "";
|
|
|
|
return {
|
|
id: tx.id ?? tx.external_id ?? "",
|
|
user: tx.customer || "",
|
|
created: formattedDate,
|
|
type: tx.type || "",
|
|
amount: tx.amount
|
|
? `${tx.amount < 0 ? "-" : ""}${Math.abs(tx.amount).toFixed(2)} ${tx.currency || ""}`
|
|
: "",
|
|
psp: tx.psp_id || "",
|
|
};
|
|
};
|
|
|
|
const transactions = reviewTransactions?.transactions || [];
|
|
const displayTransactions = transactions.map(formatTransaction);
|
|
|
|
const handleStatusChange = (rowId: number, newStatus: string) => {
|
|
setStatusDialogData({ rowId, newStatus });
|
|
};
|
|
|
|
return (
|
|
<Paper elevation={3} className="transactions-waiting-approval">
|
|
<Box sx={{ p: 3 }}>
|
|
<Box sx={{ display: "flex", justifyContent: "space-between", mb: 2 }}>
|
|
<Typography variant="h5" fontWeight="bold">
|
|
Transactions Waiting for Approval
|
|
</Typography>
|
|
<Box>
|
|
<Button variant="outlined">All Pending Withdrawals</Button>
|
|
<IconButton size="small">
|
|
<MoreVertIcon fontSize="small" />
|
|
</IconButton>
|
|
</Box>
|
|
</Box>
|
|
|
|
{reviewTransactions && (
|
|
<TableContainer
|
|
component={Paper}
|
|
sx={{
|
|
maxHeight: 400,
|
|
overflow: "auto",
|
|
}}
|
|
>
|
|
<Table>
|
|
<TableHead>
|
|
<TableRow>
|
|
<TableCell>
|
|
<strong>ID</strong>
|
|
</TableCell>
|
|
<TableCell>
|
|
<strong>User</strong>
|
|
</TableCell>
|
|
<TableCell>
|
|
<strong>Created</strong>
|
|
</TableCell>
|
|
<TableCell>
|
|
<strong>Type</strong>
|
|
</TableCell>
|
|
<TableCell>
|
|
<strong>Amount</strong>
|
|
</TableCell>
|
|
<TableCell>
|
|
<strong>PSP</strong>
|
|
</TableCell>
|
|
<TableCell>
|
|
<strong>Action</strong>
|
|
</TableCell>
|
|
</TableRow>
|
|
</TableHead>
|
|
<TableBody>
|
|
{displayTransactions.length > 0 ? (
|
|
displayTransactions.map((tx, i) => (
|
|
<TableRow key={`${tx.id}-${i}`}>
|
|
<TableCell>{tx.id}</TableCell>
|
|
<TableCell>{tx.user}</TableCell>
|
|
<TableCell>{tx.created}</TableCell>
|
|
<TableCell>{tx.type}</TableCell>
|
|
<TableCell>{tx.amount}</TableCell>
|
|
<TableCell>{tx.psp}</TableCell>
|
|
<TableCell>
|
|
<IconButton
|
|
color="success"
|
|
onClick={() => handleStatusChange(tx.id, "approved")}
|
|
>
|
|
<CheckCircleIcon />
|
|
</IconButton>
|
|
<IconButton
|
|
color="error"
|
|
onClick={() => handleStatusChange(tx.id, "declined")}
|
|
>
|
|
<CancelIcon />
|
|
</IconButton>
|
|
</TableCell>
|
|
</TableRow>
|
|
))
|
|
) : (
|
|
<TableRow>
|
|
<TableCell colSpan={7} align="center">
|
|
<Typography variant="body2" color="text.secondary">
|
|
No transactions waiting for approval
|
|
</Typography>
|
|
</TableCell>
|
|
</TableRow>
|
|
)}
|
|
</TableBody>
|
|
</Table>
|
|
</TableContainer>
|
|
)}
|
|
</Box>
|
|
<StatusChangeDialog
|
|
open={Boolean(statusDialogData)}
|
|
transactionId={statusDialogData?.rowId ?? undefined}
|
|
newStatus={statusDialogData?.newStatus ?? ""}
|
|
onClose={() => setStatusDialogData(null)}
|
|
/>
|
|
</Paper>
|
|
);
|
|
};
|