Skip to content

Commit

Permalink
Merge branch 'dev' into ALPHA-4678-share-button
Browse files Browse the repository at this point in the history
  • Loading branch information
elcharitas authored Mar 4, 2024
2 parents 7a1e1d9 + bdbc994 commit 0fbd643
Show file tree
Hide file tree
Showing 9 changed files with 159 additions and 13 deletions.
1 change: 1 addition & 0 deletions packages/frontend/src/api/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export * from "./useCookieChoice";
export * from "./useIsMobile";
export * from "./useFeatureFlags";
export * from "./useFilters";
export * from "./useFilterKeywordSearch";
export * from "./useGATracker";
export * from "./useGlobalSearch";
export * from "./useGlobalHooks";
Expand Down
69 changes: 69 additions & 0 deletions packages/frontend/src/api/hooks/useFilterKeywordSearch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { useMemo, useState } from "react";
import { useGetFilterKeywordsQuery } from "src/api/services";
import { TFilterKeyword, ESupportedFilters } from "src/api/types";

interface IFilterKeywordSearch {
searchState: string;
keywordResults: TFilterKeyword[];
isFetchingKeywordResults: boolean;
setSearchState: (s: string) => void;
}

/**
* useFilterKeywordSearch.
* Pretty similar to useKeywordSearch, but instead of consuming the keywords endpoint,
* it queries the superfeed/filter_keywords endpoint.
* The main difference is that the results are grouped in categories (concept tags, coins, projects, etc).
* This hook is used in the UserFilter page.
* It is used to search for keywords, display them and add them to the view.
*
* @returns - The search state and results.
*/
export const useFilterKeywordSearch: () => IFilterKeywordSearch = () => {
const [searchState, setSearchState] = useState("");

const { data: keywordsData, isFetching: isFetchingKeywordResults } =
useGetFilterKeywordsQuery(
{
filter_text: searchState,
},
{
skip: searchState === "",
}
);

const keywordResults = useMemo(() => {
if (!keywordsData) return [];
return [
...keywordsData.conceptTags.map((keyword) => ({
id: keyword.id,
name: keyword.name,
slug: keyword.tag.slug,
type: ESupportedFilters.ConceptTags,
})),
...keywordsData.chains.map((keyword) => ({
id: keyword.id,
name: keyword.name,
slug: keyword.tag.slug,
type: ESupportedFilters.Chains,
})),
...keywordsData.coins.map((keyword) => ({
id: keyword.id,
name: keyword.name,
slug: keyword.tag.slug,
type: ESupportedFilters.Coins,
})),
].filter(
(item, index, self) =>
self.findIndex((innerItem) => innerItem.slug === item.slug) ===
index
);
}, [keywordsData]);

return {
searchState,
setSearchState,
keywordResults,
isFetchingKeywordResults,
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import {
TGetSuperfeedFilterDataRawResponse,
TGetSuperfeedFilterDataResponse,
TGetSuperfeedFilterDataRequest,
TGetSuperfeedFilterKeywordsResponse,
TGetSuperfeedFilterKeywordsRequest,
TGetSuperfeedFilterKeywordsRawResponse,
} from "./types";

const { SUPERFEED } = CONFIG.API.DEFAULT.ROUTES;
Expand Down Expand Up @@ -89,8 +92,31 @@ export const superfeedApi = alphadayApi.injectEndpoints({
),
}),
}),
getFilterKeywords: builder.query<
TGetSuperfeedFilterKeywordsResponse,
TGetSuperfeedFilterKeywordsRequest
>({
query: (req) => {
const { ...reqParams } = req;
const params: string = queryString.stringify(reqParams);
const path = `${SUPERFEED.BASE}${SUPERFEED.FILTER_KEYWORDS}?${params}`;
Logger.debug("getSuperfeedFilterKeywords: querying", path);
return path;
},
transformResponse: (
r: TGetSuperfeedFilterKeywordsRawResponse
): TGetSuperfeedFilterKeywordsResponse => ({
coins: r.coin_keywords,
conceptTags: r.concept_keywords,
chains: r.chain_keywords,
}),
}),
}),
overrideExisting: false,
});

export const { useGetSuperfeedListQuery, useGetFilterDataQuery } = superfeedApi;
export const {
useGetSuperfeedListQuery,
useGetFilterDataQuery,
useGetFilterKeywordsQuery,
} = superfeedApi;
24 changes: 24 additions & 0 deletions packages/frontend/src/api/services/superfeed/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,16 @@ export type TTaggedFilterDatum = TBaseFilterItem & {
tags: TBaseFilterTag[];
};

export type TRemoteFilterKeyword = {
id: number;
name: string;
tag: {
id: number;
name: string;
slug: string;
};
};

/**
* Query types
*/
Expand Down Expand Up @@ -75,3 +85,17 @@ export type TGetSuperfeedFilterDataResponse = {
coins: TTaggedFilterDatum[];
chains: TTaggedFilterDatum[];
};

export type TGetSuperfeedFilterKeywordsRequest = {
filter_text: string;
};
export type TGetSuperfeedFilterKeywordsRawResponse = {
concept_keywords: TRemoteFilterKeyword[];
coin_keywords: TRemoteFilterKeyword[];
chain_keywords: TRemoteFilterKeyword[];
};
export type TGetSuperfeedFilterKeywordsResponse = {
conceptTags: TRemoteFilterKeyword[];
coins: TRemoteFilterKeyword[];
chains: TRemoteFilterKeyword[];
};
7 changes: 7 additions & 0 deletions packages/frontend/src/api/types/superfeed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ export enum ETimeRange {
Last6Months = "last-6-months",
}

export type TFilterKeyword = {
id: number;
name: string;
slug: string;
type: ESupportedFilters;
};

export type TFeedMarketData = {
coin: {
name: string;
Expand Down
1 change: 1 addition & 0 deletions packages/frontend/src/config/backend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ const API_V0 = {
BASE: "superfeed",
DEFAULT: "/",
FILTER_DATA: "/filter_data/",
FILTER_KEYWORDS: "/filter_keywords/",
},
TVL: {
BASE: "tvl",
Expand Down
13 changes: 6 additions & 7 deletions packages/frontend/src/mobile-components/FilterSearchBar.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@
import { FC } from "react";
import { SearchBar } from "@alphaday/ui-kit";
import { TBaseFilterItem } from "src/api/services";
import { Logger } from "src/api/utils/logging";

type TOption = TBaseFilterItem;

interface FilterSearchBarProps {
interface FilterSearchBarProps<T extends TBaseFilterItem = TOption> {
tags?: string;
tagsList: TOption[];
tagsList: T[];
setSearchState: (value: string) => void;
onChange: (value: readonly TOption[]) => void;
onChange: (value: readonly T[]) => void;
}

const FilterSearchBar: FC<FilterSearchBarProps> = ({
const FilterSearchBar = <T extends TBaseFilterItem>({
onChange,
tags,
setSearchState,
tagsList,
}) => {
}: FilterSearchBarProps<T>) => {
const searchValues = tags
?.split(",")
.map((tag) => {
Expand All @@ -31,7 +30,7 @@ const FilterSearchBar: FC<FilterSearchBarProps> = ({
data-testid="header-search-container"
>
<span className="w-full max-w-[524px]">
<SearchBar<TOption>
<SearchBar<T>
showBackdrop
onChange={(o) => {
Logger.debug("onChange called");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import {
Toggle,
themeColors,
} from "@alphaday/ui-kit";
import { ESortFeedBy, ESupportedFilters } from "src/api/types";
import { ESortFeedBy, ESupportedFilters, TFilterKeyword } from "src/api/types";
import { ReactComponent as ChevronSVG } from "src/assets/icons/chevron-down2.svg";
// import FilterSearchBar from "../FilterSearchBar";
import FilterSearchBar from "../FilterSearchBar";
import { TFilterOptions } from "./filterOptions";
import { OptionsDisclosure, OptionButton } from "./OptionsDisclosure";

Expand All @@ -17,6 +17,8 @@ interface IUserFiltersModalProps {
filterOptions: TFilterOptions;
isLoading: boolean;
onSelectFilter: (slug: string, type: ESupportedFilters) => void;
filterKeywords: TFilterKeyword[];
onSearchInputChange: (value: string) => void;
}

const UserFiltersModal: FC<IUserFiltersModalProps> = ({
Expand All @@ -25,6 +27,8 @@ const UserFiltersModal: FC<IUserFiltersModalProps> = ({
filterOptions,
isLoading,
onSelectFilter,
filterKeywords,
onSearchInputChange,
}) => {
const [isOpen, setIsOpen] = useState(true);

Expand Down Expand Up @@ -70,9 +74,20 @@ const UserFiltersModal: FC<IUserFiltersModalProps> = ({
Craft your ideal superfeed by customizing the
filters below.
</p>
{/* TODO: implement filter search when properly spec-ed */}
<div className="flex relative z-10 justify-center [&>div]:w-full">
{/* <FilterSearchBar /> */}
<FilterSearchBar<TFilterKeyword>
setSearchState={onSearchInputChange}
tagsList={filterKeywords.map((kw) => ({
...kw,
label: kw.name,
value: kw.slug,
}))}
onChange={(values) =>
values.forEach((kw) =>
onSelectFilter(kw.slug, kw.type)
)
}
/>
</div>
</div>
<div className="w-full flex justify-between py-6 border-b border-borderLine">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { FC } from "react";
import { useFilters } from "src/api/hooks";
import { useFilters, useFilterKeywordSearch } from "src/api/hooks";
import {
useGetFilterDataQuery,
TFilterDatum,
Expand Down Expand Up @@ -101,6 +101,8 @@ const UserFiltersContainer: FC<{

const { toggleFilter } = useFilters();

const { setSearchState, keywordResults } = useFilterKeywordSearch();

const filterOptions: TFilterOptions = {
localFilterOptions: updateLocalFilterOptionsState(selectedLocalFilters),
syncedFilterOptions: {
Expand Down Expand Up @@ -146,6 +148,8 @@ const UserFiltersContainer: FC<{
filterOptions={filterOptions}
isLoading={isLoading}
onSelectFilter={handleSelectFilter}
filterKeywords={keywordResults}
onSearchInputChange={setSearchState}
/>
);
};
Expand Down

0 comments on commit 0fbd643

Please sign in to comment.