diff --git a/src/components/history/History.tsx b/src/components/history/History.tsx
new file mode 100644
index 0000000..6cb056d
--- /dev/null
+++ b/src/components/history/History.tsx
@@ -0,0 +1,110 @@
+import { Alert, Box, Button, ButtonBase, DialogActions, DialogContent, DialogTitle, IconButton, InputLabel, Snackbar, SnackbarCloseReason, TextField, Typography, styled } from '@mui/material'
+import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react'
+import { BootstrapDialog } from '../Terms'
+import CloseIcon from '@mui/icons-material/Close';
+import { Spacer } from '../common/Spacer';
+import gameContext from '../../contexts/gameContext';
+import HistoryList from './HistoryList';
+import RefreshIcon from "@mui/icons-material/Refresh";
+
+
+
+
+export const History = ({qortAddress, show}) => {
+ const [buyHistory, setBuyHistory] = useState({})
+ const [sellHistory, setSellHistory] = useState({})
+
+ const { getCoinLabel, selectedCoin} = useContext(gameContext)
+ const [mode, setMode] = useState('buyHistory')
+ const [open, setOpen] = useState(false)
+
+ const selectedHistory = useMemo(()=> {
+ if(mode === 'buyHistory') return buyHistory[selectedCoin] || []
+ if(mode === 'sellHistory') return sellHistory[selectedCoin] || []
+ }, [selectedCoin, buyHistory, sellHistory, mode])
+ const getBuyHistory = useCallback((address, foreignBlockchain, mode, limit = 20)=> {
+ setOpen(true)
+ let historyUrl
+ if(mode === 'buyHistory'){
+ historyUrl = `/crosschain/trades?foreignBlockchain=${foreignBlockchain}&buyerAddress=${address}&limit=${limit}&reverse=true`;
+
+ }
+ if(mode === 'sellHistory'){
+ historyUrl = `/crosschain/trades?foreignBlockchain=${foreignBlockchain}&sellerAddress=${address}&limit=${limit}&reverse=true`;
+
+ }
+
+
+
+ fetch(historyUrl)
+ .then((response) => {
+ return response.json();
+ })
+ .then((data) => {
+ if(mode === 'buyHistory'){
+ setBuyHistory((prev)=> {
+ return {
+ ...prev,
+ [foreignBlockchain]: data
+ }
+ })
+ }
+ if(mode === 'sellHistory'){
+ setSellHistory((prev)=> {
+ return {
+ ...prev,
+ [foreignBlockchain]: data
+ }
+ })
+ }
+
+ }).catch(()=> {}).finally(()=> {
+ setOpen(false)
+ })
+ }, [])
+
+ useEffect(()=> {
+ if(!qortAddress || !selectedCoin) return
+ if(mode === 'buyHistory' && buyHistory[selectedCoin])return
+ if(mode === 'sellHistory' && sellHistory[selectedCoin])return
+
+ getBuyHistory(qortAddress, selectedCoin, mode)
+ }, [qortAddress, selectedCoin, buyHistory, mode])
+
+ return (
+
+
+
+
{
+ getBuyHistory(qortAddress, selectedCoin, mode)
+ }}>
+
+
+
Showing most recent 20 results
+
+
{
+ setOpen(false)
+ }}
+ >
+ setOpen(false)}
+ severity="info"
+ variant="filled"
+ sx={{ width: "100%" }}
+ >
+ {'Fetching History'}
+
+
+
+ )
+}
diff --git a/src/components/history/HistoryList.tsx b/src/components/history/HistoryList.tsx
new file mode 100644
index 0000000..dd680a3
--- /dev/null
+++ b/src/components/history/HistoryList.tsx
@@ -0,0 +1,190 @@
+import { ColDef } from "ag-grid-community";
+import { AgGridReact } from "ag-grid-react";
+import React, {
+ useCallback,
+ useContext,
+ useEffect,
+ useMemo,
+ useRef,
+ useState,
+} from "react";
+import { autoSizeStrategy, baseLocalHost } from "../Grids/TradeOffers";
+import { Alert, Box, Snackbar, SnackbarCloseReason, Typography } from "@mui/material";
+import gameContext from "../../contexts/gameContext";
+import { formatTimestampForum } from "../../utils/formatTime";
+
+const defaultColDef = {
+ resizable: true, // Make columns resizable by default
+ sortable: true, // Make columns sortable by default
+ suppressMovable: true, // Prevent columns from being movable
+};
+
+
+
+export default function HistoryList({ qortAddress, historyList }) {
+ const gridRef = useRef(null);
+ console.log('historyList', historyList)
+ const { getCoinLabel, selectedCoin} = useContext(gameContext)
+ const [qortalNames, setQortalNames] = useState({});
+
+
+ const onGridReady = useCallback((params: any) => {
+ params.api.sizeColumnsToFit(); // Adjust columns to fit the grid width
+ const allColumnIds = params.columnApi
+ .getAllColumns()
+ .map((col: any) => col.getColId());
+ params.columnApi.autoSizeColumns(allColumnIds); // Automatically adjust the width to fit content
+ }, []);
+
+ const getName = async (address) => {
+ try {
+ const response = await fetch("/names/address/" + address);
+ const nameData = await response.json();
+ if (nameData?.length > 0) {
+ setQortalNames((prev) => {
+ return {
+ ...prev,
+ [address]: nameData[0].name,
+ };
+ });
+ } else {
+ setQortalNames((prev) => {
+ return {
+ ...prev,
+ [address]: null,
+ };
+ });
+ }
+ } catch (error) {
+ // error
+ }
+ };
+
+
+ const columnDefs: ColDef[] = useMemo(()=> {
+ return [
+ {
+ headerName: "QORT AMOUNT",
+ field: "qortAmount",
+ flex: 1, // Flex makes this column responsive
+ minWidth: 150, // Ensure it doesn't shrink too much
+ resizable: true,
+ },
+ {
+ headerName: `${getCoinLabel()}/QORT`,
+ valueGetter: (params) =>
+ +params.data.foreignAmount / +params.data.qortAmount,
+ sortable: true,
+ flex: 1, // Flex makes this column responsive
+ minWidth: 150, // Ensure it doesn't shrink too much
+ resizable: true,
+ },
+ {
+ headerName: `Total ${getCoinLabel()} Value`,
+ field: "foreignAmount",
+ flex: 1, // Flex makes this column responsive
+ minWidth: 150, // Ensure it doesn't shrink too much
+ resizable: true,
+ },
+ {
+ headerName: "Time",
+ field: "tradeTimestamp",
+ valueGetter: (params) =>
+ formatTimestampForum(params.data.tradeTimestamp),
+ flex: 1, // Flex makes this column responsive
+ minWidth: 200, // Ensure it doesn't shrink too much
+ resizable: true,
+ },
+ {
+ headerName: "Buyer",
+ field: "buyerReceivingAddress",
+ flex: 1, // Flex makes this column responsive
+ minWidth: 200, // Ensure it doesn't shrink too much
+ resizable: true,
+ valueGetter: (params) => {
+ if (params?.data?.buyerReceivingAddress) {
+ if (qortalNames[params?.data?.buyerReceivingAddress]) {
+ return qortalNames[params?.data?.buyerReceivingAddress];
+ } else if (qortalNames[params?.data?.buyerReceivingAddress] === undefined) {
+ getName(params?.data?.buyerReceivingAddress);
+
+ return params?.data?.buyerReceivingAddress;
+ } else {
+ return params?.data?.buyerReceivingAddress;
+ }
+ }
+ },
+ },
+ {
+ headerName: "Seller",
+ field: "sellerAddress",
+ flex: 1, // Flex makes this column responsive
+ minWidth: 200, // Ensure it doesn't shrink too much
+ resizable: true,
+ valueGetter: (params) => {
+ if (params?.data?.sellerAddress) {
+ if (qortalNames[params?.data?.sellerAddress]) {
+ return qortalNames[params?.data?.sellerAddress];
+ } else if (qortalNames[params?.data?.sellerAddress] === undefined) {
+ getName(params?.data?.sellerAddress);
+
+ return params?.data?.sellerAddress;
+ } else {
+ return params?.data?.sellerAddress;
+ }
+ }
+ },
+ },
+ ];
+
+ }, [selectedCoin, qortalNames])
+
+
+
+ // const onSelectionChanged = (event: any) => {
+ // const selectedRows = event.api.getSelectedRows();
+ // if(selectedRows[0]){
+ // setSelectedTrade(selectedRows[0])
+ // } else {
+ // setSelectedTrade(null)
+ // }
+ // };
+
+
+
+
+
+
+
+ return (
+
+
+
params.data.qortalAtAddress} // Ensure rows have unique IDs
+ />
+
+
+ );
+}
diff --git a/src/components/sell/TradeBotList.tsx b/src/components/sell/TradeBotList.tsx
index c317868..c619787 100644
--- a/src/components/sell/TradeBotList.tsx
+++ b/src/components/sell/TradeBotList.tsx
@@ -18,47 +18,7 @@ const defaultColDef = {
suppressMovable: true, // Prevent columns from being movable
};
-// const columnDefs: ColDef[] = [
-// {
-// headerCheckboxSelection: false, // Adds a checkbox in the header for selecting all rows
-// checkboxSelection: true, // Adds checkboxes in each row for selection
-// headerName: "Select", // You can customize the header name
-// width: 50, // Adjust the width as needed
-// pinned: "left", // Optional, to pin this column on the left
-// resizable: false,
-// },
-// {
-// headerName: "QORT AMOUNT",
-// field: "qortAmount",
-// flex: 1, // Flex makes this column responsive
-// minWidth: 150, // Ensure it doesn't shrink too much
-// resizable: true,
-// },
-// {
-// headerName: "LTC/QORT",
-// valueGetter: (params) =>
-// +params.data.foreignAmount / +params.data.qortAmount,
-// sortable: true,
-// sort: "asc",
-// flex: 1, // Flex makes this column responsive
-// minWidth: 150, // Ensure it doesn't shrink too much
-// resizable: true,
-// },
-// {
-// headerName: "Total LTC Value",
-// field: "foreignAmount",
-// flex: 1, // Flex makes this column responsive
-// minWidth: 150, // Ensure it doesn't shrink too much
-// resizable: true,
-// },
-// {
-// headerName: "Status",
-// field: "status",
-// flex: 1, // Flex makes this column responsive
-// minWidth: 300, // Ensure it doesn't shrink too much
-// resizable: true,
-// },
-// ];
+
export default function TradeBotList({ qortAddress, failedTradeBots }) {
const [tradeBotList, setTradeBotList] = useState([]);
diff --git a/src/pages/Home/Home.tsx b/src/pages/Home/Home.tsx
index bdac02b..4a75776 100644
--- a/src/pages/Home/Home.tsx
+++ b/src/pages/Home/Home.tsx
@@ -16,6 +16,7 @@ import { Spacer } from "../../components/common/Spacer";
import { ReusableModal } from "../../components/common/reusable-modal/ReusableModal";
import { OAuthButton, OAuthButtonRow } from "./Home-Styles";
import { CreateSell } from "../../components/sell/CreateSell";
+import { History } from "../../components/history/History";
interface IsInstalledProps {}
@@ -34,7 +35,7 @@ export const HomePage: FC = ({}) => {
selectedCoin
} = useContext(gameContext);
const { setNotification } = useContext(NotificationContext);
- const [mode, setMode] = useState("buy");
+ const [mode, setMode] = useState("history");
const filteredOngoingTrades = useMemo(()=> {
return onGoingTrades?.filter((item)=> item?.tradeInfo?.foreignBlockchain === selectedCoin)
}, [onGoingTrades, selectedCoin])
@@ -108,6 +109,7 @@ export const HomePage: FC = ({}) => {
+
>
);
diff --git a/src/utils/formatTime.ts b/src/utils/formatTime.ts
index bc26d72..6bc2c01 100644
--- a/src/utils/formatTime.ts
+++ b/src/utils/formatTime.ts
@@ -1,6 +1,25 @@
+import moment from "moment";
+
export function formatTime(seconds: number): string {
const minutes = Math.floor(seconds / 60);
const remainingSeconds = seconds % 60;
// Pad the seconds with a leading zero if less than 10
return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`;
}
+
+
+export function formatTimestampForum(timestamp: number): string {
+ const now = moment();
+ const timestampMoment = moment(timestamp);
+ const elapsedTime = now.diff(timestampMoment, 'minutes');
+
+ if (elapsedTime < 1) {
+ return `Just now - ${timestampMoment.format('h:mm A')}`;
+ } else if (elapsedTime < 60) {
+ return `${elapsedTime}m ago - ${timestampMoment.format('h:mm A')}`;
+ } else if (elapsedTime < 1440) {
+ return `${Math.floor(elapsedTime / 60)}h ago - ${timestampMoment.format('h:mm A')}`;
+ } else {
+ return timestampMoment.format('MMM D, YYYY - h:mm A');
+ }
+}
\ No newline at end of file