mirror of
https://github.com/luxfi/explore.git
synced 2026-09-24 00:28:18 +00:00
use string type for category
This commit is contained in:
@@ -1,15 +1,10 @@
|
||||
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 }
|
||||
|
||||
+11
-13
@@ -1,25 +1,24 @@
|
||||
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>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
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',
|
||||
};
|
||||
@@ -1,7 +1,9 @@
|
||||
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)) {
|
||||
|
||||
Reference in New Issue
Block a user