Skip to content

Commit

Permalink
Merge pull request #20 from cryptoalgebra/fix/position-filter
Browse files Browse the repository at this point in the history
split positions / pools tables
  • Loading branch information
lilchizh authored Apr 3, 2024
2 parents 93abb69 + 3f66583 commit 0fd1435
Show file tree
Hide file tree
Showing 13 changed files with 590 additions and 437 deletions.
17 changes: 16 additions & 1 deletion src/components/common/Settings/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { Separator } from "@/components/ui/separator";
import { Switch } from "@/components/ui/switch";
import { useUserState } from "@/state/userStore";
import { Percent } from "@cryptoalgebra/integral-sdk";
import { SettingsIcon } from "lucide-react";
Expand All @@ -15,11 +16,12 @@ const Settings = () => {
<SettingsIcon />
</Button>
</PopoverTrigger>
<PopoverContent align={'end'} className="flex flex-col gap-2 w-fit bg-card rounded-3xl border border-card-border text-white">
<PopoverContent align={'end'} className="flex flex-col gap-4 w-fit bg-card rounded-3xl border border-card-border text-white">
<div className="text-md font-bold">Transaction Settings</div>
<Separator orientation={'horizontal'} className="bg-border" />
<SlippageTolerance />
<TransactionDeadline />
<ExpertMode />
</PopoverContent>
</Popover>

Expand Down Expand Up @@ -149,5 +151,18 @@ const TransactionDeadline = () => {
</div>

}
const ExpertMode = () => {
const { isExpertMode, actions: { setIsExpertMode } } = useUserState();

return <div className="flex flex-col gap-2 max-w-[332px]">
<div className="flex justify-between items-center gap-2 text-md font-semibold">
Expert Mode
<Switch checked={isExpertMode} onCheckedChange={setIsExpertMode} />
</div>
<p className="whitespace-break-spaces">
Advanced control over swap parameters such as price setting and gas management.
</p>
</div>
}

export default Settings;
398 changes: 0 additions & 398 deletions src/components/common/Table/dataTable.tsx

This file was deleted.

12 changes: 12 additions & 0 deletions src/components/common/Table/loadingState.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Skeleton } from '@/components/ui/skeleton';

export const LoadingState = () => (
<div className="flex flex-col w-full gap-4 p-4">
{[1, 2, 3, 4].map((v) => (
<Skeleton
key={`table-skeleton-${v}`}
className="w-full h-[50px] bg-card-light rounded-xl"
/>
))}
</div>
);
322 changes: 322 additions & 0 deletions src/components/common/Table/myPositionsTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,322 @@
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from '@/components/ui/table';
import { cn } from '@/lib/utils';
import { usePositionFilterStore } from '@/state/positionFilterStore';
import {
ColumnDef,
ColumnFiltersState,
SortingState,
flexRender,
getCoreRowModel,
getFilteredRowModel,
getSortedRowModel,
useReactTable,
} from '@tanstack/react-table';
import { ChevronDown } from 'lucide-react';
import { useCallback, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { LoadingState } from './loadingState';
import { PositionsStatus } from '@/types/position-filter-status';

interface MyPositionsTableProps<TData, TValue> {
columns: ColumnDef<TData, TValue>[];
data: TData[];
selectedRow?: number;
action?: (args?: any) => void;
defaultSortingID?: string;
link?: string;
showPagination?: boolean;
searchID?: string;
loading?: boolean;
}

const MyPositionsTable = <TData, TValue>({
columns,
data,
selectedRow,
action,
link,
defaultSortingID,
loading,
}: MyPositionsTableProps<TData, TValue>) => {
const [sorting, setSorting] = useState<SortingState>(
defaultSortingID ? [{ id: defaultSortingID, desc: true }] : []
);
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);

const [expandActive, setExpandActive] = useState(true);
const [expandOnFarming, setExpandOnFarming] = useState(true);
const [expandClosed, setExpandClosed] = useState(true);

const { filterStatus } = usePositionFilterStore();

const navigate = useNavigate();

const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
onSortingChange: setSorting,
getSortedRowModel: getSortedRowModel(),
onColumnFiltersChange: setColumnFilters,
getFilteredRowModel: getFilteredRowModel(),
state: {
sorting,
columnFilters,
},
});

const activePositions = data.filter(
(pos: any) => !pos.inFarming && !pos.isClosed
);

const farmingPositions = data.filter(
(pos: any) => pos.inFarming && !pos.isClosed
);

const closedPositions = data.filter((pos: any) => pos.isClosed);

const noActivePositions =
filterStatus.Active && activePositions.length === 0;
const noFarmingPositions =
filterStatus.OnFarming && farmingPositions.length === 0;
const noClosedPositions =
filterStatus.Closed && closedPositions.length === 0;

const renderHeaderRow = useCallback(
(positionStatus: PositionsStatus) => {
const isStatusActive = positionStatus === PositionsStatus.ACTIVE;
const isStatusOnFarming =
positionStatus === PositionsStatus.ON_FARMING;
const isStatusClosed = positionStatus === PositionsStatus.CLOSED;
return (
<TableRow
key={'active-positions'}
className="hover:bg-transparent h-full cursor-pointer"
onClick={() => {
if (isStatusActive) setExpandActive(!expandActive);
if (isStatusOnFarming)
setExpandOnFarming(!expandOnFarming);
if (isStatusClosed) setExpandClosed(!expandClosed);
}}
>
<td
colSpan={columns.length}
className="pl-8 h-12 text-left whitespace-nowrap"
>
<span className="flex gap-4 items-center">
{isStatusActive && 'Active'}
{isStatusOnFarming && 'On Farming'}
{isStatusClosed && 'Closed'}
<ChevronDown
className={cn(
'opacity-50 transition-transform ease-in-out duration-200 mt-auto',
isStatusActive &&
!expandActive &&
'-rotate-90 opacity-100',
isStatusOnFarming &&
!expandOnFarming &&
'-rotate-90 opacity-100',
isStatusClosed &&
!expandClosed &&
'-rotate-90 opacity-100'
)}
size={18}
/>
</span>
</td>
</TableRow>
);
},
[expandActive, expandOnFarming, expandClosed, columns.length]
);

const renderPositions = useCallback(
(positionStatus: PositionsStatus) => {
const isStatusActive = positionStatus === PositionsStatus.ACTIVE;
const isStatusOnFarming =
positionStatus === PositionsStatus.ON_FARMING;
const isStatusClosed = positionStatus === PositionsStatus.CLOSED;

return table.getRowModel().rows.map((row: any) => {
const isSelected =
Number(selectedRow) === Number(row.original.id);
if (
(isStatusActive &&
!row.original.inFarming &&
!row.original.isClosed) ||
(isStatusOnFarming &&
row.original.inFarming &&
!row.original.isClosed) ||
(isStatusClosed && row.original.isClosed)
) {
return (
<TableRow
key={row.id}
data-state={row.getIsSelected() && 'selected'}
className={`border-card-border/40 ${
isSelected
? 'bg-muted-primary/60'
: 'bg-card-dark'
} ${(action || link) && 'cursor-pointer'} ${
action || link
? isSelected
? 'hover:bg-muted-primary'
: 'hover:bg-card-hover'
: 'hover:bg-card-dark'
} ${
isStatusActive &&
!expandActive &&
'collapse border-0 opacity-0'
} ${
isStatusOnFarming &&
!expandOnFarming &&
'collapse border-0 opacity-0'
}
${
isStatusClosed &&
!expandClosed &&
'collapse border-0 opacity-0'
}`}
onClick={() => {
if (action) {
action(row.original.id);
} else if (link) {
navigate(`/${link}/${row.original.id}`);
}
}}
>
{row.getVisibleCells().map((cell: any) => (
<TableCell key={cell.id} className="text-left">
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
</TableCell>
))}
</TableRow>
);
} else return null;
});
},
[
action,
link,
expandActive,
expandOnFarming,
expandClosed,
selectedRow,
table,
navigate,
]
);

if (loading) return <LoadingState />;

return (
<>
<Table>
<TableHeader className="[&_tr]:border-b [&_tr]:border-opacity-30">
{table.getHeaderGroups().map((headerGroup) => (
<TableRow
key={headerGroup.id}
className="hover:bg-transparent"
>
{headerGroup.headers.map((header) => (
<TableHead
key={header.id}
className="rounded-xl text-white font-semibold [&_svg]:mt-auto"
>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext()
)}
</TableHead>
))}
</TableRow>
))}
</TableHeader>
<TableBody className="[&_tr]:border-opacity-30 hover:bg-transparent text-[16px]">
{table.getRowModel().rows?.length === 0 ||
(!filterStatus.Active &&
!filterStatus.Closed &&
!filterStatus.OnFarming) ||
(noActivePositions &&
noFarmingPositions &&
!filterStatus.Closed) ||
(noActivePositions &&
noClosedPositions &&
!filterStatus.OnFarming) ||
(noActivePositions &&
!filterStatus.Closed &&
!filterStatus.OnFarming) ||
(noFarmingPositions &&
noClosedPositions &&
!filterStatus.Active) ||
(noFarmingPositions &&
!filterStatus.Active &&
!filterStatus.Closed) ||
(noClosedPositions &&
!filterStatus.Active &&
!filterStatus.OnFarming) ? (
<TableRow className="hover:bg-card h-full border-0">
<TableCell
colSpan={columns.length}
className="h-24 text-center"
>
No results.
</TableCell>
</TableRow>
) : (
<>
{activePositions.length > 0 &&
filterStatus.Active && (
<>
{renderHeaderRow(
PositionsStatus.ACTIVE
)}
{renderPositions(
PositionsStatus.ACTIVE
)}
</>
)}

{farmingPositions.length > 0 &&
filterStatus.OnFarming && (
<>
{renderHeaderRow(
PositionsStatus.ON_FARMING
)}
{renderPositions(
PositionsStatus.ON_FARMING
)}
</>
)}
{closedPositions.length > 0 &&
filterStatus.Closed && (
<>
{renderHeaderRow(
PositionsStatus.CLOSED
)}
{renderPositions(
PositionsStatus.CLOSED
)}
</>
)}
</>
)}
</TableBody>
</Table>
</>
);
};

export default MyPositionsTable;
Loading

0 comments on commit 0fd1435

Please sign in to comment.