Skip to content

Commit

Permalink
add dApp filter
Browse files Browse the repository at this point in the history
  • Loading branch information
snoopy1412 committed Jul 8, 2024
1 parent 81c466b commit b523fa4
Show file tree
Hide file tree
Showing 16 changed files with 335 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,11 @@ const TableChainFilter = ({
<Separator />
<div className="flex flex-col px-[1.25rem] lg:grid lg:grid-cols-3">
{sortedOptions.map(({ value: optionValue, label }) => {
const isSelected = value.includes(optionValue);
const isSelected = value.includes(optionValue as number);
return (
<div
key={optionValue}
onClick={() => toggleItem(optionValue)}
onClick={() => toggleItem(optionValue as number)}
className={cn(
'flex items-center gap-[0.62rem] py-[0.62rem]',
value.length < limit || isSelected ? 'cursor-pointer' : 'cursor-not-allowed'
Expand Down
121 changes: 121 additions & 0 deletions src/components/data-table/DesktopFilterToolbar/TableDappFilter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import SelectedLabels from '@/components/selected-labels';
import { Button } from '@/components/ui/button';
import { Command, CommandGroup, CommandItem, CommandList } from '@/components/ui/command';
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
import { cn } from '@/lib/utils';
import { TableFilterOption } from '@/types/helper';
import { CheckIcon } from '@radix-ui/react-icons';
import { ChevronDown } from 'lucide-react';
import { useState } from 'react';
import dappConfig from '@/dappRemark/config.json';
import { capitalize } from 'lodash-es';
import { DAppConfigKeys } from '@/utils';

interface TableDappFilterProps {
value: DAppConfigKeys[];
onChange: (newValue: DAppConfigKeys[]) => void;
title: React.ReactNode;
onClearFilters?: () => void;
buttonClassName?: string;
contentClassName?: string;
}

const TableDappFilter = ({
value,
onChange,
title,
onClearFilters,
buttonClassName,
contentClassName
}: TableDappFilterProps) => {
const [open, setOpen] = useState(false);

const options: TableFilterOption[] = Object.keys(dappConfig)?.map((dapp) => ({
label: capitalize(dapp),
value: dapp
}));

const toggleItem = (itemValue: DAppConfigKeys) => {
if (value.includes(itemValue)) {
onChange(value.filter((s) => s !== itemValue));
} else {
onChange([...value, itemValue]);
}
};

return (
<Popover onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
size="sm"
className={cn(
'flex items-center gap-[0.31rem] border-none text-sm font-normal',
buttonClassName
)}
>
<span className="text-secondary-foreground">{title}:</span>
<div className="flex items-center gap-[0.31rem]">
<SelectedLabels options={options} value={value} />
<ChevronDown
size={16}
strokeWidth={1.5}
className={cn('transform transition-transform', open ? 'rotate-180' : 'rotate-0')}
/>
</div>
</Button>
</PopoverTrigger>
<PopoverContent className={cn('p-0', contentClassName)} align="end">
<Command>
<CommandList>
<CommandGroup className="p-0">
{options.map(({ value: optionValue, label }) => {
const isSelected = value.includes(optionValue as DAppConfigKeys);
return (
<CommandItem
key={optionValue}
onSelect={() => toggleItem(optionValue as DAppConfigKeys)}
className="cursor-pointer px-[1.25rem] py-[0.62rem]"
>
<div
className={cn(
'mr-2 flex h-4 w-4 items-center justify-center rounded-sm border border-primary',
isSelected
? 'bg-primary text-primary-foreground [&_svg]:visible'
: 'opacity-50 [&_svg]:invisible'
)}
>
<CheckIcon className={cn('h-4 w-4', isSelected ? 'visible' : 'invisible')} />
</div>
<span
className={cn(
'text-sm',
isSelected ? 'text-foreground' : 'text-secondary-foreground'
)}
>
{label}
</span>
</CommandItem>
);
})}
</CommandGroup>
{value.length > 0 && (
<>
<CommandGroup>
<CommandItem
onSelect={onClearFilters}
className="cursor-pointer justify-center text-center text-sm text-secondary-foreground"
>
Clear filters
</CommandItem>
</CommandGroup>
</>
)}
</CommandList>
</Command>
</PopoverContent>
</Popover>
);
};

export default TableDappFilter;
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
import SelectedLabels from '@/components/selected-labels';
import { Button } from '@/components/ui/button';
import {
Command,
CommandGroup,
CommandItem,
CommandList,
CommandSeparator
} from '@/components/ui/command';
import { Command, CommandGroup, CommandItem, CommandList } from '@/components/ui/command';
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
import { cn } from '@/lib/utils';
import { TableFilterOption } from '@/types/helper';
Expand Down Expand Up @@ -70,11 +64,11 @@ const TableStatusFilter = ({
<CommandList>
<CommandGroup className="p-0">
{options.map(({ value: optionValue, label }) => {
const isSelected = value.includes(optionValue);
const isSelected = value.includes(optionValue as number);
return (
<CommandItem
key={optionValue}
onSelect={() => toggleItem(optionValue)}
onSelect={() => toggleItem(optionValue as number)}
className="cursor-pointer px-[1.25rem] py-[0.62rem]"
>
<div
Expand Down
19 changes: 17 additions & 2 deletions src/components/data-table/DesktopFilterToolbar/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Button } from '@/components/ui/button';

import { MESSAGE_STATUS_LIST } from '@/config/status';
import TableDappFilter from './TableDappFilter';
import TableChainFilter from './TableChainFilter';
import TableStatusFilter from './TableStatusFilter';
import TableDateFilter from './TableDateFilter';
Expand All @@ -12,29 +13,43 @@ import { CHAIN } from '@/types/chains';
export interface TableFilterToolbarProps {
chains: CHAIN[];
className?: string;
hideDappFilter?: boolean;
}
const TableFilterToolbar = ({ chains, className }: TableFilterToolbarProps) => {
const TableFilterToolbar = ({ chains, className, hideDappFilter }: TableFilterToolbarProps) => {
const CHAIN_OPTIONS = chains?.map((chain) => ({
label: chain.name,
value: chain.id
}));
const {
selectedDapps,
selectedStatuses,
date,
selectedSourceChains,
selectedTargetChains,
handleDappChange,
handleStatusChange,
handleDateChange,
handleSourceChainChange,
handleTargetChainChange,
handleReset,
handleResetStatus
handleResetStatus,
handleResetDapps
} = useFilter();
const limit = CHAIN_OPTIONS?.length;
return (
<div className={cn('flex items-center justify-between py-5', className)}>
<div className="text-sm font-normal leading-[1.4rem] text-foreground">Messages</div>
<div className="flex gap-3">
{!hideDappFilter && (
<TableDappFilter
value={selectedDapps}
onChange={handleDappChange}
title="Dapp"
onClearFilters={handleResetDapps}
contentClassName="w-[10rem]"
/>
)}

<TableStatusFilter
options={MESSAGE_STATUS_LIST}
value={selectedStatuses}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,11 @@ const TableChainFilter = ({ options, value, onChange, limit }: TableChainFilterP
<Separator />
<div className="flex flex-col">
{sortedOptions.map(({ value: optionValue, label }) => {
const isSelected = value.includes(optionValue);
const isSelected = value.includes(optionValue as number);
return (
<div
key={optionValue}
onClick={() => toggleItem(optionValue)}
onClick={() => toggleItem(optionValue as number)}
className={cn(
'flex h-[3.125rem] items-center gap-[0.62rem]',
value.length < limit || isSelected ? 'cursor-pointer' : 'cursor-not-allowed'
Expand Down
67 changes: 67 additions & 0 deletions src/components/data-table/MobileFilterToolbar/TableDappFilter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { Button } from '@/components/ui/button';
import { cn } from '@/lib/utils';
import { TableFilterOption } from '@/types/helper';
import { DAppConfigKeys } from '@/utils';
import { CheckIcon } from '@radix-ui/react-icons';

interface TableDappFilterProps {
value: DAppConfigKeys[];
options: TableFilterOption[];
onChange: (newValue: DAppConfigKeys[]) => void;
onClearFilters?: () => void;
}

const TableDappFilter = ({ value, options, onChange, onClearFilters }: TableDappFilterProps) => {
const toggleItem = (itemValue: DAppConfigKeys) => {
if (value.includes(itemValue)) {
onChange(value.filter((s) => s !== itemValue));
} else {
onChange([...value, itemValue]);
}
};

return (
<>
<div className="absolute left-0 top-0 w-[calc(100vw-3rem)] bg-background">
{options.map(({ value: optionValue, label }) => {
const isSelected = value.includes(optionValue as DAppConfigKeys);
return (
<div
key={optionValue}
onClick={() => toggleItem(optionValue as DAppConfigKeys)}
className="flex items-center gap-2 py-[0.62rem]"
>
<div
className={cn(
'mr-2 flex h-4 w-4 items-center justify-center rounded-sm border border-primary',
isSelected
? 'bg-primary text-primary-foreground [&_svg]:visible'
: 'opacity-50 [&_svg]:invisible'
)}
>
<CheckIcon className={cn('h-4 w-4', isSelected ? 'visible' : 'invisible')} />
</div>
<span
className={cn(
'text-sm',
isSelected ? 'text-foreground' : 'text-secondary-foreground'
)}
>
{label}
</span>
</div>
);
})}
<Button
size="sm"
className="mt-5 w-full border-none bg-card px-0 text-sm font-normal text-foreground hover:bg-card/80 hover:text-foreground/80"
onClick={onClearFilters}
>
Reset
</Button>
</div>
</>
);
};

export default TableDappFilter;
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ const TableStatusFilter = ({
<>
<div className="absolute left-0 top-0 w-[calc(100vw-3rem)] bg-background">
{options.map(({ value: optionValue, label }) => {
const isSelected = value.includes(optionValue);
const isSelected = value.includes(optionValue as number);
return (
<div
key={optionValue}
onClick={() => toggleItem(optionValue)}
onClick={() => toggleItem(optionValue as number)}
className="flex items-center gap-2 py-[0.62rem]"
>
<div
Expand Down
Loading

0 comments on commit b523fa4

Please sign in to comment.