Files
explore/ui/address/mud/AddressMudTable.tsx

166 lines
5.3 KiB
TypeScript

import { useRouter } from 'next/router';
import React from 'react';
import type { AddressMudRecordsFilter, AddressMudRecordsSorting } from 'types/api/address';
import useIsMobile from 'lib/hooks/useIsMobile';
import { cn } from 'lib/utils/cn';
import getQueryParamString from 'lib/router/getQueryParamString';
import { Tag } from '@luxfi/ui/tag';
import { ContentLoader } from 'toolkit/components/loaders/ContentLoader';
import ActionBar, { ACTION_BAR_HEIGHT_DESKTOP } from 'ui/shared/ActionBar';
import DataListDisplay from 'ui/shared/DataListDisplay';
import Pagination from 'ui/shared/pagination/Pagination';
import useQueryWithPages from 'ui/shared/pagination/useQueryWithPages';
import { getNextOrderValue } from 'ui/shared/sort/getNextSortValue';
import getSortParamsFromQuery from 'ui/shared/sort/getSortParamsFromQuery';
import AddressMudBreadcrumbs from './AddressMudBreadcrumbs';
import AddressMudRecordsTable from './AddressMudRecordsTable';
import { getNameTypeText, SORT_SEQUENCE } from './utils';
const BREADCRUMBS_HEIGHT = 60;
const FILTERS_HEIGHT = 44;
type Props = {
isQueryEnabled?: boolean;
tableId: string;
};
type FilterKeys = keyof AddressMudRecordsFilter;
const AddressMudTable = ({ tableId, isQueryEnabled = true }: Props) => {
const router = useRouter();
const [ sorting, setSorting ] =
React.useState<AddressMudRecordsSorting | undefined>(getSortParamsFromQuery<AddressMudRecordsSorting>(router.query, SORT_SEQUENCE));
const [ filters, setFilters ] = React.useState<AddressMudRecordsFilter>({});
const isMobile = useIsMobile();
const [ tableHasHorizontalScroll, setTableHasHorizontalScroll ] = React.useState(isMobile);
const hash = getQueryParamString(router.query.hash);
const { data, isLoading, isError, pagination, onSortingChange } = useQueryWithPages({
resourceName: 'general:mud_records',
pathParams: { hash, table_id: tableId },
filters,
sorting,
options: {
// no placeholder data because the structure of a table is unpredictable
enabled: isQueryEnabled,
},
});
const handleTableHasHorizontalScroll = React.useCallback(() => {
setTableHasHorizontalScroll((prev) => !prev);
}, []);
const toggleSorting = React.useCallback((val: AddressMudRecordsSorting['sort']) => {
const newSorting = { sort: val, order: getNextOrderValue(sorting?.sort === val ? sorting.order : undefined) };
setSorting(newSorting);
onSortingChange(newSorting);
}, [ onSortingChange, sorting ]);
const onRemoveFilterClick = React.useCallback((key: FilterKeys) => () => {
setFilters(prev => {
const newFilters = { ...prev };
delete newFilters[key];
return newFilters;
});
}, []);
const hasActiveFilters = Object.values(filters).some(Boolean);
const actionBarHeight = React.useMemo(() => {
const heightWithoutFilters = pagination.isVisible ? ACTION_BAR_HEIGHT_DESKTOP : BREADCRUMBS_HEIGHT;
return hasActiveFilters ? heightWithoutFilters + FILTERS_HEIGHT : heightWithoutFilters;
}, [ pagination.isVisible, hasActiveFilters ]);
if (isLoading) {
return <ContentLoader/>;
}
const filtersTags = hasActiveFilters ? (
<div className="flex flex-row flex-wrap gap-3 mb-1">
{ Object.entries(filters).map(([ key, value ]) => {
const index = key as FilterKeys === 'filter_key0' ? 0 : 1;
return (
<Tag
key={ key }
variant="filter"
label={ getNameTypeText(data?.schema.key_names[index] || '', data?.schema.key_types[index] || '') }
closable
onClose={ onRemoveFilterClick(key as FilterKeys) }
className="max-w-[360px]"
>
{ value }
</Tag>
);
}) }
</div>
) : null;
const breadcrumbs = data ? (
<AddressMudBreadcrumbs
hash={ hash }
tableId={ tableId }
tableName={ data?.table.table_full_name }
/>
) : null;
const actionBar = (!isMobile || hasActiveFilters || pagination.isVisible) && (
<ActionBar className={ cn('-mt-6 justify-between', hasActiveFilters ? 'items-start' : 'items-center') } showShadow={ tableHasHorizontalScroll }>
<div>
{ !isMobile && breadcrumbs }
{ filtersTags }
</div>
<Pagination className="lg:ml-8" { ...pagination }/>
</ActionBar>
);
const content = data?.items ? (
<AddressMudRecordsTable
data={ data }
top={ actionBarHeight }
sorting={ sorting }
toggleSorting={ toggleSorting }
setFilters={ setFilters }
filters={ filters }
toggleTableHasHorizontalScroll={ handleTableHasHorizontalScroll }
hash={ hash }
/>
) : null;
const emptyText = (
<>
<span>There are no records for </span>
{ data?.table.table_full_name ? <span className="font-semibold">{ data?.table.table_full_name }</span> : 'this table' }
</>
);
return (
<>
{ isMobile && (
<div className="mb-6">{ breadcrumbs }</div>
) }
<DataListDisplay
isError={ isError }
itemsNum={ data?.items.length }
emptyText={ emptyText }
hasActiveFilters={ hasActiveFilters }
emptyStateProps={{
term: 'record',
}}
actionBar={ actionBar }
showActionBarIfEmpty={ !isMobile }
className={ data?.items.length ? 'mt-0' : 'mt-2' }
>
{ content }
</DataListDisplay>
</>
);
};
export default AddressMudTable;