Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CFE-418]: feat(components): update filter selection to support input type string #917

1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Improvements

- [#917](https://github.com/alleslabs/celatone-frontend/pull/917) Update filter selection input to support multiple use case
- [#826](https://github.com/alleslabs/celatone-frontend/pull/826) Apply dynamic component theme generation
- [#795](https://github.com/alleslabs/celatone-frontend/pull/795) Rebranding
- [#907](https://github.com/alleslabs/celatone-frontend/pull/907) Migrate mahalo and minitias from 2 to 3
Expand Down
7 changes: 2 additions & 5 deletions src/lib/components/filter/FilterInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,11 @@ import { Flex, FormLabel, Input } from "@chakra-ui/react";
import type { Dispatch, ForwardedRef, RefObject, SetStateAction } from "react";

import { DropdownChevron } from "../DropdownChevron";
import type { ProposalStatus, ProposalType } from "lib/types";
import { mergeRefs } from "lib/utils";

type Result = ProposalType | ProposalStatus;

interface FilterInputProps {
keyword: string;
result: Result[];
result: string[];
isDropdown: boolean;
chipContainerComponent: JSX.Element;
inputRef: RefObject<HTMLInputElement>;
Expand Down Expand Up @@ -49,7 +46,7 @@ export const FilterInput = ({
autoComplete="off"
size="lg"
minW="150px"
placeholder={result.length ? "" : placeholder}
placeholder={result.length > 0 ? "" : placeholder}
ref={mergeRefs([inputRef, ref])}
maxLength={36}
style={{ border: 0, maxHeight: "54px" }}
Expand Down
39 changes: 28 additions & 11 deletions src/lib/pages/proposals/components/ProposalStatusFilter.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type { InputProps } from "@chakra-ui/react";
import { Flex, FormControl, useOutsideClick } from "@chakra-ui/react";
import { matchSorter } from "match-sorter";
import type { Dispatch, SetStateAction } from "react";
import { forwardRef, useMemo, useRef, useState } from "react";

import { AmpEvent, trackUseFilter } from "lib/amplitude";
import { useTierConfig } from "lib/app-provider";
import {
DropdownContainer,
FilterChip,
Expand All @@ -13,17 +13,17 @@ import {
} from "lib/components/filter";
import { StatusChip } from "lib/components/table";
import { ProposalStatus } from "lib/types";
import { toggleItem } from "lib/utils";

export interface ProposalStatusFilterProps extends InputProps {
result: ProposalStatus[];
minW?: string;
label?: string;
placeholder?: string;
setResult: Dispatch<SetStateAction<ProposalStatus[]>>;
setResult: (option: ProposalStatus[]) => void;
isMulti: boolean;
}

const OPTIONS = Object.values(ProposalStatus);

export const ProposalStatusFilter = forwardRef<
HTMLInputElement,
ProposalStatusFilterProps
Expand All @@ -35,13 +35,24 @@ export const ProposalStatusFilter = forwardRef<
setResult,
placeholder,
label,
isMulti,
}: ProposalStatusFilterProps,
ref
) => {
const tier = useTierConfig();
const [keyword, setKeyword] = useState("");
const [isDropdown, setIsDropdown] = useState(false);
const inputRef = useRef<HTMLInputElement>(null);
const boxRef = useRef<HTMLDivElement>(null);
const isFullTier = tier === "full";

const OPTIONS = isFullTier
? Object.values(ProposalStatus)
: Object.values(ProposalStatus).filter(
(status) =>
status !== ProposalStatus.DEPOSIT_FAILED &&
status !== ProposalStatus.CANCELLED
);

const dropdownValue = useMemo(
() =>
Expand All @@ -50,22 +61,28 @@ export const ProposalStatusFilter = forwardRef<
threshold: matchSorter.rankings.CONTAINS,
})
: OPTIONS,
[keyword]
[keyword, OPTIONS]
);

const isOptionSelected = (option: ProposalStatus) =>
result.some((selectedOption) => selectedOption === option);

const selectOption = (option: ProposalStatus) => {
if (inputRef.current) {
setKeyword("");
}
setKeyword("");

if (result.includes(option)) {
trackUseFilter(AmpEvent.USE_FILTER_PROPOSALS_STATUS, result, "remove");
setResult((prevState) => prevState.filter((value) => value !== option));
} else {
trackUseFilter(AmpEvent.USE_FILTER_PROPOSALS_STATUS, result, "add");
setResult((prevState) => [...prevState, option]);
}

if (!isMulti) {
setIsDropdown(false);

if (result[0] === option) setResult([]);
else setResult([option]);
} else {
setResult(toggleItem(result, option));
}
};

Expand All @@ -92,7 +109,7 @@ export const ProposalStatusFilter = forwardRef<
<FilterChip
key={option}
chipComponent={<StatusChip status={option} hasCloseBtn />}
onSelect={() => selectOption(option)}
onSelect={() => setResult(toggleItem(result, option))}
/>
))}
</Flex>
Expand Down
1 change: 1 addition & 0 deletions src/lib/pages/proposals/components/ProposalsTableFull.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ export const ProposalsTableFull = () => {
result={statuses}
setResult={setStatuses}
placeholder="All Status"
isMulti
/>
<ProposalTypeFilter
label="Filter by Type"
Expand Down
11 changes: 8 additions & 3 deletions src/lib/pages/proposals/components/ProposalsTableLite.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,14 @@ import { EmptyState, ErrorFetching } from "lib/components/state";
import { ProposalsTable } from "lib/components/table";
import { useDebounce } from "lib/hooks";
import { useProposalDataLcd, useProposalsLcd } from "lib/services/proposal";
import type { ProposalStatus } from "lib/types";

import { ProposalStatusFilter } from "./ProposalStatusFilter";

export const ProposalsTableLite = () => {
const [search, setSearch] = useState("");
const debouncedSearch = useDebounce(search);
const [status, setStatus] = useState<ProposalStatus[]>([]);

const {
data: proposalsData,
Expand All @@ -19,7 +23,7 @@ export const ProposalsTableLite = () => {
hasNextPage,
isLoading: isProposalsLoading,
isFetchingNextPage,
} = useProposalsLcd("");
} = useProposalsLcd(status[0]);

const { data: proposalData, isLoading: isProposalDataLoading } =
useProposalDataLcd(debouncedSearch);
Expand Down Expand Up @@ -53,12 +57,13 @@ export const ProposalsTableLite = () => {
/>
</GridItem>
<GridItem>
{/* <ProposalStatusFilter
<ProposalStatusFilter
label="Filter by Status"
result={status}
setResult={setStatus}
placeholder="All Status"
/> */}
isMulti={false}
/>
</GridItem>
</Grid>
<ProposalsTable
Expand Down
7 changes: 7 additions & 0 deletions src/lib/utils/array.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const toggleItem = <T>(array: T[], item: T): T[] => {
if (array.includes(item)) {
return array.filter((i) => i !== item);
}

return [...array, item];
};
1 change: 1 addition & 0 deletions src/lib/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,4 @@ export * from "./txHash";
export * from "./validate";
export * from "./window";
export * from "./zod";
export * from "./array";