Commit 845f1e73 authored by tom's avatar tom

use string type for category

parent 39f47a6e
export type MarketplaceCategoriesIds = 'all' | 'favorites' | 'defi' | 'exchanges' | 'finance' | 'games' | 'marketplaces' | 'nft' |
'security' | 'social' | 'tools' | 'yieldFarming';
export type MarketplaceCategory = { id: MarketplaceCategoriesIds; name: string }
export type AppItemPreview = {
id: string;
external?: boolean;
title: string;
logo: string;
shortDescription: string;
categories: Array<MarketplaceCategoriesIds>;
categories: Array<string>;
url: string;
}
......@@ -21,3 +16,8 @@ export type AppItemOverview = AppItemPreview & {
telegram?: string;
github?: string;
}
export enum AppCategory {
ALL = 'All apps',
FAVORITES = 'Favorites',
}
......@@ -4,7 +4,7 @@ import {
} from '@chakra-ui/react';
import React, { useCallback } from 'react';
import type { AppItemOverview, MarketplaceCategoriesIds } from 'types/client/apps';
import type { AppItemOverview } from 'types/client/apps';
import linkIcon from 'icons/link.svg';
import ghIcon from 'icons/social/git.svg';
......@@ -155,7 +155,7 @@ const AppModal = ({
</Heading>
<Box marginBottom={ 2 }>
{ categories.map((category: MarketplaceCategoriesIds) => (
{ categories.map((category) => (
<Tag
colorScheme="blue"
marginRight={ 2 }
......
import { Box, Button, Icon, Menu, MenuButton, MenuList } from '@chakra-ui/react';
import React from 'react';
import type { MarketplaceCategoriesIds, MarketplaceCategory } from 'types/client/apps';
import { AppCategory } from 'types/client/apps';
import eastMiniArrowIcon from 'icons/arrows/east-mini.svg';
import CategoriesMenuItem from './CategoriesMenuItem';
type Props = {
categories: Array<MarketplaceCategoriesIds>;
selectedCategoryId: MarketplaceCategoriesIds;
onSelect: (category: MarketplaceCategoriesIds) => void;
categories: Array<string>;
selectedCategoryId: string;
onSelect: (category: string) => void;
}
const CategoriesMenu = ({ selectedCategoryId, onSelect, categories }: Props) => {
const options = React.useMemo(() => ([
{ id: 'Favorites', name: 'Favorites' },
{ id: 'App apps', name: 'App apps' },
...categories.map((category) => ({ id: category, name: category })),
AppCategory.FAVORITES,
AppCategory.ALL,
...categories,
]), [ categories ]);
const selectedCategory = options.find(category => category.id === selectedCategoryId);
return (
<Menu>
......@@ -37,17 +36,16 @@ const CategoriesMenu = ({ selectedCategoryId, onSelect, categories }: Props) =>
display="flex"
alignItems="center"
>
{ selectedCategory?.name }
{ selectedCategoryId }
<Icon transform="rotate(-90deg)" ml={{ base: 'auto', sm: 1 }} as={ eastMiniArrowIcon } w={ 5 } h={ 5 }/>
</Box>
</MenuButton>
<MenuList zIndex={ 3 }>
{ options.map((category: MarketplaceCategory) => (
{ options.map((category: string) => (
<CategoriesMenuItem
key={ category.id }
id={ category.id }
name={ category.name }
key={ category }
id={ category }
onClick={ onSelect }
/>
)) }
......
......@@ -2,21 +2,20 @@ import { Icon, MenuItem } from '@chakra-ui/react';
import type { FunctionComponent, SVGAttributes } from 'react';
import React, { useCallback } from 'react';
import type { MarketplaceCategoriesIds } from 'types/client/apps';
import { AppCategory } from 'types/client/apps';
import starFilledIcon from 'icons/star_filled.svg';
type Props = {
id: MarketplaceCategoriesIds;
name: string;
onClick: (category: MarketplaceCategoriesIds) => void;
id: string;
onClick: (category: string) => void;
}
const ICONS = {
favorites: starFilledIcon,
} as { [key in MarketplaceCategoriesIds]: FunctionComponent<SVGAttributes<SVGElement>> };
const ICONS: Record<string, FunctionComponent<SVGAttributes<SVGElement>>> = {
[AppCategory.FAVORITES]: starFilledIcon,
};
const CategoriesMenuItem = ({ id, name, onClick }: Props) => {
const CategoriesMenuItem = ({ id, onClick }: Props) => {
const handleSelection = useCallback(() => {
onClick(id);
}, [ id, onClick ]);
......@@ -28,11 +27,8 @@ const CategoriesMenuItem = ({ id, name, onClick }: Props) => {
display="flex"
alignItems="center"
>
{ id in ICONS && (
<Icon mr={ 3 } as={ ICONS[id] } w={ 4 } h={ 4 } color="blackAlpha.800"/>
) }
{ name }
{ id in ICONS && <Icon mr={ 3 } as={ ICONS[id] } w={ 4 } h={ 4 } color="blackAlpha.800"/> }
{ id }
</MenuItem>
);
};
......
import type { MarketplaceCategoriesIds } from 'types/client/apps';
export const APP_CATEGORIES: {[key in MarketplaceCategoriesIds]: string} = {
favorites: 'Favorites',
all: 'All apps',
defi: 'DeFi',
exchanges: 'Exchanges',
finance: 'Finance',
games: 'Games',
marketplaces: 'Marketplaces',
nft: 'NFT',
security: 'Security',
social: 'Social',
tools: 'Tools',
yieldFarming: 'Yield farming',
};
import { useQuery } from '@tanstack/react-query';
import _unique from 'lodash/uniq';
import React, { useCallback, useEffect, useState } from 'react';
import type { AppItemOverview, MarketplaceCategoriesIds } from 'types/client/apps';
import type { AppItemOverview } from 'types/client/apps';
import { AppCategory } from 'types/client/apps';
import appConfig from 'configs/app/config';
import type { ResourceError } from 'lib/api/resources';
......@@ -22,15 +24,15 @@ function isAppNameMatches(q: string, app: AppItemOverview) {
return app.title.toLowerCase().includes(q.toLowerCase());
}
function isAppCategoryMatches(category: MarketplaceCategoriesIds, app: AppItemOverview, favoriteApps: Array<string>) {
return category === 'all' ||
(category === 'favorites' && favoriteApps.includes(app.id)) ||
function isAppCategoryMatches(category: string, app: AppItemOverview, favoriteApps: Array<string>) {
return category === AppCategory.ALL ||
(category === AppCategory.FAVORITES && favoriteApps.includes(app.id)) ||
app.categories.includes(category);
}
export default function useMarketplaceApps() {
const [ selectedAppId, setSelectedAppId ] = useState<string | null>(null);
const [ selectedCategoryId, setSelectedCategoryId ] = useState<MarketplaceCategoriesIds>('all');
const [ selectedCategoryId, setSelectedCategoryId ] = useState<string>(AppCategory.ALL);
const [ filterQuery, setFilterQuery ] = useState('');
const [ favoriteApps, setFavoriteApps ] = useState<Array<string>>([]);
......@@ -63,7 +65,7 @@ export default function useMarketplaceApps() {
const debouncedFilterQuery = useDebounce(filterQuery, 500);
const clearSelectedAppId = useCallback(() => setSelectedAppId(null), []);
const handleCategoryChange = useCallback((newCategory: MarketplaceCategoriesIds) => {
const handleCategoryChange = useCallback((newCategory: string) => {
setSelectedCategoryId(newCategory);
}, []);
......@@ -72,7 +74,7 @@ export default function useMarketplaceApps() {
}, [ selectedCategoryId, data, debouncedFilterQuery, favoriteApps ]);
const categories = React.useMemo(() => {
return data?.map(app => app.categories).flat() || [];
return _unique(data?.map(app => app.categories).flat()) || [];
}, [ data ]);
useEffect(() => {
......
......@@ -27,7 +27,7 @@ const MarketplaceApp = () => {
const id = getQueryParamString(router.query.id);
const { isLoading, isError, error, data } = useQuery<unknown, ResourceError<unknown>, AppItemOverview>(
[ 'marketplace-apps' ],
[ 'marketplace-apps', id ],
async() => {
const result = await apiFetch<Array<AppItemOverview>, unknown>(appConfig.marketplaceConfigUrl || '');
if (!Array.isArray(result)) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment