wip: add My Orders fetching multiple pages & filtering
This commit is contained in:
parent
451e53e244
commit
daecf49bc0
2 changed files with 196 additions and 106 deletions
|
|
@ -12,6 +12,7 @@ export type GetUserOrdersData = {
|
|||
limit: number;
|
||||
offset: number;
|
||||
filterInfo: {
|
||||
pairId?: number;
|
||||
status?: GetUserOrdersBodyStatus;
|
||||
type?: GetUserOrdersBodyType;
|
||||
date?: {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,10 @@ import PairValue from '@/interfaces/props/pages/dex/orders/PairValue';
|
|||
import DateState from '@/interfaces/common/DateState';
|
||||
import useUpdateUser from '@/hook/useUpdateUser';
|
||||
import { Footer } from '@/zano_ui/src';
|
||||
import { GetUserOrdersBodyStatus } from '@/interfaces/fetch-data/get-user-orders/GetUserOrdersData';
|
||||
import {
|
||||
GetUserOrdersBodyStatus,
|
||||
GetUserOrdersBodyType,
|
||||
} from '@/interfaces/fetch-data/get-user-orders/GetUserOrdersData';
|
||||
import Decimal from 'decimal.js';
|
||||
import { useInView } from 'react-intersection-observer';
|
||||
import Preloader from '@/components/UI/Preloader/Preloader';
|
||||
|
|
@ -25,13 +28,6 @@ const ORDERS_PER_PAGE = 10;
|
|||
function Orders() {
|
||||
const fetchUser = useUpdateUser();
|
||||
|
||||
const { ref: inViewRef } = useInView({
|
||||
threshold: 0,
|
||||
onChange: (inView) => {
|
||||
console.log('In view:', inView);
|
||||
},
|
||||
});
|
||||
|
||||
const ordersCategories = [
|
||||
{
|
||||
name: 'Active orders',
|
||||
|
|
@ -75,117 +71,214 @@ function Orders() {
|
|||
});
|
||||
|
||||
const [orders, setOrders] = useState<UserOrderData[]>([]);
|
||||
const [lastOrderOffset, setLastOrderOffset] = useState(0);
|
||||
const [totalOrdersCount, setTotalOrdersCount] = useState<number | undefined>(undefined);
|
||||
const [orderPageLoading, setOrderPageLoading] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
async function initPairsDropdown() {
|
||||
try {
|
||||
const getUserOrdersAllPairsRes = await fetchMethods.getUserOrdersAllPairs();
|
||||
function deriveFiltersFromState() {
|
||||
const status =
|
||||
categoryState.code === 'active-orders'
|
||||
? GetUserOrdersBodyStatus.ACTIVE
|
||||
: GetUserOrdersBodyStatus.FINISHED;
|
||||
|
||||
if (!getUserOrdersAllPairsRes.success) {
|
||||
throw new Error('Error fetching pairs for orders');
|
||||
}
|
||||
|
||||
const ordersPairs = getUserOrdersAllPairsRes.data;
|
||||
|
||||
const statePairs = ordersPairs.map((e) => ({
|
||||
name: `${e.firstCurrency.ticker}/${e.secondCurrency.ticker}`,
|
||||
code: new Decimal(e.id).toFixed(),
|
||||
}));
|
||||
|
||||
setPairsValues([{ name: 'All pairs', code: '' }, ...statePairs]);
|
||||
} catch (error) {
|
||||
console.error('Error while initPairsDropdown:', error);
|
||||
}
|
||||
}
|
||||
|
||||
async function initOrders() {
|
||||
const getUserOrdersRes = await fetchMethods.getUserOrders({
|
||||
limit: ORDERS_PER_PAGE,
|
||||
offset: 0,
|
||||
filterInfo: {
|
||||
status: GetUserOrdersBodyStatus.ACTIVE,
|
||||
},
|
||||
});
|
||||
|
||||
if (!getUserOrdersRes.success) {
|
||||
throw new Error('Error fetching user orders');
|
||||
const type = (() => {
|
||||
if (buyDropdownValue.name === 'Buy & Sell') {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
setOrders(getUserOrdersRes.data);
|
||||
return getUserOrdersRes.data;
|
||||
return buyDropdownValue.name === 'Buy'
|
||||
? GetUserOrdersBodyType.BUY
|
||||
: GetUserOrdersBodyType.SELL;
|
||||
})();
|
||||
|
||||
const pairId =
|
||||
pairDropdownValue.code === ''
|
||||
? undefined
|
||||
: new Decimal(pairDropdownValue.code).toNumber();
|
||||
|
||||
const date = (() => {
|
||||
if (!dateRange.first || !dateRange.last) return undefined;
|
||||
|
||||
const firstDate = new Date(dateRange.first);
|
||||
const lastDate = new Date(dateRange.last);
|
||||
|
||||
firstDate.setHours(0, 0, 0, 0);
|
||||
lastDate.setHours(23, 59, 59, 999);
|
||||
|
||||
return {
|
||||
from: firstDate.getTime(),
|
||||
to: lastDate.getTime(),
|
||||
};
|
||||
})();
|
||||
|
||||
return {
|
||||
status,
|
||||
type,
|
||||
pairId,
|
||||
date,
|
||||
};
|
||||
}
|
||||
|
||||
async function addNewOrdersPage() {
|
||||
const { status, type, pairId, date } = deriveFiltersFromState();
|
||||
|
||||
const getUserOrdersRes = await fetchMethods.getUserOrders({
|
||||
limit: ORDERS_PER_PAGE,
|
||||
offset: lastOrderOffset,
|
||||
filterInfo: {
|
||||
status,
|
||||
type,
|
||||
pairId,
|
||||
date,
|
||||
},
|
||||
});
|
||||
|
||||
if (!getUserOrdersRes.success) {
|
||||
throw new Error('Error fetching user orders');
|
||||
}
|
||||
|
||||
async function initialize() {
|
||||
const newOrders = getUserOrdersRes.data;
|
||||
const newOrdersAmount = newOrders.length;
|
||||
|
||||
setOrders((prev) => [...prev, ...newOrders]);
|
||||
setLastOrderOffset((prev) => prev + newOrdersAmount);
|
||||
setTotalOrdersCount(getUserOrdersRes.totalItemsCount);
|
||||
}
|
||||
|
||||
const { ref: inViewRef } = useInView({
|
||||
threshold: 0,
|
||||
onChange: async (inView) => {
|
||||
if (!inView || !initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (totalOrdersCount !== undefined && lastOrderOffset >= totalOrdersCount) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (orderPageLoading) {
|
||||
return;
|
||||
}
|
||||
|
||||
setOrderPageLoading(true);
|
||||
|
||||
try {
|
||||
setAlertState('loading');
|
||||
setAlertSubtitle('Loading orders data...');
|
||||
|
||||
// Simulate loading time
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
|
||||
await fetchUser();
|
||||
|
||||
await initPairsDropdown();
|
||||
|
||||
await initOrders();
|
||||
|
||||
setInitialized(true);
|
||||
setAlertState(null);
|
||||
setAlertSubtitle('');
|
||||
await addNewOrdersPage();
|
||||
} catch (error) {
|
||||
console.error('Error during initialization:', error);
|
||||
console.error('Error fetching new orders page:', error);
|
||||
|
||||
setAlertState('error');
|
||||
setAlertSubtitle('Error loading orders data');
|
||||
setAlertSubtitle('Error loading more orders');
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 2000));
|
||||
|
||||
setAlertState(null);
|
||||
setAlertSubtitle('');
|
||||
} finally {
|
||||
setOrderPageLoading(false);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
async function initPairsDropdown() {
|
||||
try {
|
||||
const getUserOrdersAllPairsRes = await fetchMethods.getUserOrdersAllPairs();
|
||||
|
||||
if (!getUserOrdersAllPairsRes.success) {
|
||||
throw new Error('Error fetching pairs for orders');
|
||||
}
|
||||
|
||||
const ordersPairs = getUserOrdersAllPairsRes.data;
|
||||
|
||||
const statePairs = ordersPairs.map((e) => ({
|
||||
name: `${e.firstCurrency.ticker}/${e.secondCurrency.ticker}`,
|
||||
code: new Decimal(e.id).toFixed(),
|
||||
}));
|
||||
|
||||
setPairsValues([{ name: 'All pairs', code: '' }, ...statePairs]);
|
||||
} catch (error) {
|
||||
console.error('Error while initPairsDropdown:', error);
|
||||
}
|
||||
}
|
||||
|
||||
async function initOrders() {
|
||||
const { status, type, pairId, date } = deriveFiltersFromState();
|
||||
|
||||
const getUserOrdersRes = await fetchMethods.getUserOrders({
|
||||
limit: ORDERS_PER_PAGE,
|
||||
offset: 0,
|
||||
filterInfo: {
|
||||
status,
|
||||
type,
|
||||
pairId,
|
||||
date,
|
||||
},
|
||||
});
|
||||
|
||||
if (!getUserOrdersRes.success) {
|
||||
throw new Error('Error fetching user orders');
|
||||
}
|
||||
|
||||
const newOrders = getUserOrdersRes.data;
|
||||
const newOrdersAmount = newOrders.length;
|
||||
|
||||
setOrders(newOrders);
|
||||
setLastOrderOffset(newOrdersAmount);
|
||||
setTotalOrdersCount(getUserOrdersRes.totalItemsCount);
|
||||
|
||||
return newOrders;
|
||||
}
|
||||
|
||||
async function initialize() {
|
||||
try {
|
||||
setAlertState('loading');
|
||||
setAlertSubtitle('Loading orders data...');
|
||||
|
||||
setOrders([]);
|
||||
setLastOrderOffset(0);
|
||||
setTotalOrdersCount(undefined);
|
||||
|
||||
// Simulate loading time
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
|
||||
await fetchUser();
|
||||
|
||||
await initPairsDropdown();
|
||||
|
||||
await initOrders();
|
||||
|
||||
setInitialized(true);
|
||||
setAlertState(null);
|
||||
setAlertSubtitle('');
|
||||
} catch (error) {
|
||||
console.error('Error during initialization:', error);
|
||||
|
||||
setAlertState('error');
|
||||
setAlertSubtitle('Error loading orders data');
|
||||
await new Promise((resolve) => setTimeout(resolve, 2000));
|
||||
setAlertState(null);
|
||||
setAlertSubtitle('');
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
async function onFilterChange() {
|
||||
if (!initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
await initialize();
|
||||
}
|
||||
|
||||
onFilterChange();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [buyDropdownValue, pairDropdownValue, dateRange, categoryState]);
|
||||
|
||||
useEffect(() => {
|
||||
initialize();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
function buySellFilter(e: UserOrderData) {
|
||||
if (buyDropdownValue.name === 'Buy & Sell') return true;
|
||||
|
||||
if (buyDropdownValue.name === 'Buy') return e.type === 'buy';
|
||||
|
||||
if (buyDropdownValue.name === 'Sell') return e.type === 'sell';
|
||||
}
|
||||
|
||||
function pairFilter(e: UserOrderData) {
|
||||
if (!pairDropdownValue) return true;
|
||||
|
||||
return !pairDropdownValue.code || e.pair_id === pairDropdownValue.code;
|
||||
}
|
||||
|
||||
function dateFilter(e: UserOrderData) {
|
||||
if (!dateRange.first || !dateRange.last) return true;
|
||||
const firstDate = new Date(dateRange.first);
|
||||
const lastDate = new Date(dateRange.last);
|
||||
|
||||
const timestamp = parseInt(e.timestamp, 10);
|
||||
|
||||
firstDate.setHours(0, 0, 0, 0);
|
||||
lastDate.setHours(24, 0, 0, 0);
|
||||
|
||||
if (!dateRange.first && !dateRange.last) return true;
|
||||
|
||||
if (dateRange.first && !dateRange.last) return timestamp >= firstDate.getTime();
|
||||
|
||||
if (!dateRange.first && dateRange.last) return timestamp <= lastDate.getTime();
|
||||
|
||||
return timestamp >= firstDate.getTime() && timestamp <= lastDate.getTime();
|
||||
}
|
||||
|
||||
function categoryFilter(e: UserOrderData) {
|
||||
if (categoryState.code === 'active-orders') {
|
||||
return e.status === 'active';
|
||||
}
|
||||
return e.status === 'finished';
|
||||
}
|
||||
|
||||
const activeOrders = orders.filter((e) => e.status === 'active');
|
||||
|
||||
async function cancelAllOrders() {
|
||||
|
|
@ -277,11 +370,7 @@ function Orders() {
|
|||
</div>
|
||||
|
||||
<OrdersTable
|
||||
value={orders
|
||||
.filter(buySellFilter)
|
||||
.filter(pairFilter)
|
||||
.filter(dateFilter)
|
||||
.filter(categoryFilter)}
|
||||
value={orders}
|
||||
setAlertState={setAlertState}
|
||||
setAlertSubtitle={setAlertSubtitle}
|
||||
setOrders={setOrders}
|
||||
|
|
@ -289,7 +378,7 @@ function Orders() {
|
|||
/>
|
||||
|
||||
<div className={styles['orders__preloader-wrapper']} ref={inViewRef}>
|
||||
<Preloader />
|
||||
{orderPageLoading && <Preloader />}
|
||||
</div>
|
||||
</div>
|
||||
{alertState && (
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue