Browse Source

style: add an icon for each category in the dropdown select

Nicolas Meienberger 2 years ago
parent
commit
41863f364a

+ 34 - 15
src/client/core/constants.ts

@@ -1,24 +1,43 @@
+import {
+  Icon,
+  IconBook,
+  IconBrain,
+  IconBroadcast,
+  IconCamera,
+  IconCode,
+  IconDatabase,
+  IconDeviceGamepad2,
+  IconMovie,
+  IconMusic,
+  IconPigMoney,
+  IconRobot,
+  IconShieldLock,
+  IconStar,
+  IconTool,
+  IconUsers,
+} from '@tabler/icons-react';
 import { AppCategory } from './types';
 import { AppCategory } from './types';
 
 
 type AppCategoryEntry = {
 type AppCategoryEntry = {
   name: string;
   name: string;
   id: AppCategory;
   id: AppCategory;
-  icon: string;
+  icon: Icon;
 };
 };
 
 
 export const APP_CATEGORIES: AppCategoryEntry[] = [
 export const APP_CATEGORIES: AppCategoryEntry[] = [
-  { name: 'Network', id: 'network', icon: 'FaNetworkWired' },
-  { name: 'Media', id: 'media', icon: 'FaVideo' },
-  { name: 'Development', id: 'development', icon: 'FaCode' },
-  { name: 'Automation', id: 'automation', icon: 'FaRobot' },
-  { name: 'Social', id: 'social', icon: 'FaUserFriends' },
-  { name: 'Utilities', id: 'utilities', icon: 'FaWrench' },
-  { name: 'Photography', id: 'photography', icon: 'FaCamera' },
-  { name: 'Security', id: 'security', icon: 'FaShieldAlt' },
-  { name: 'Featured', id: 'featured', icon: 'FaStar' },
-  { name: 'Books', id: 'books', icon: 'FaBook' },
-  { name: 'Data', id: 'data', icon: 'FaDatabase' },
-  { name: 'Music', id: 'music', icon: 'FaMusic' },
-  { name: 'Finance', id: 'finance', icon: 'FaMoneyBillAlt' },
-  { name: 'Gaming', id: 'gaming', icon: 'FaGamepad' },
+  { name: 'Network', id: 'network', icon: IconBroadcast },
+  { name: 'Media', id: 'media', icon: IconMovie },
+  { name: 'Development', id: 'development', icon: IconCode },
+  { name: 'Automation', id: 'automation', icon: IconRobot },
+  { name: 'Social', id: 'social', icon: IconUsers },
+  { name: 'Utilities', id: 'utilities', icon: IconTool },
+  { name: 'Photography', id: 'photography', icon: IconCamera },
+  { name: 'Security', id: 'security', icon: IconShieldLock },
+  { name: 'Featured', id: 'featured', icon: IconStar },
+  { name: 'Books', id: 'books', icon: IconBook },
+  { name: 'Data', id: 'data', icon: IconDatabase },
+  { name: 'Music', id: 'music', icon: IconMusic },
+  { name: 'Finance', id: 'finance', icon: IconPigMoney },
+  { name: 'Gaming', id: 'gaming', icon: IconDeviceGamepad2 },
+  { name: 'AI', id: 'ai', icon: IconBrain },
 ];
 ];

+ 41 - 2
src/client/modules/AppStore/components/CategorySelector/CategorySelector.tsx

@@ -1,22 +1,57 @@
 import React from 'react';
 import React from 'react';
-import Select, { SingleValue } from 'react-select';
+import Select, { SingleValue, OptionProps, ControlProps, components } from 'react-select';
+import { Icon } from '@tabler/icons-react';
 import { APP_CATEGORIES } from '../../../../core/constants';
 import { APP_CATEGORIES } from '../../../../core/constants';
 import { AppCategory } from '../../../../core/types';
 import { AppCategory } from '../../../../core/types';
 import { useUIStore } from '../../../../state/uiStore';
 import { useUIStore } from '../../../../state/uiStore';
 
 
+const { Option, Control } = components;
+
 interface IProps {
 interface IProps {
   onSelect: (value?: AppCategory) => void;
   onSelect: (value?: AppCategory) => void;
   className?: string;
   className?: string;
   initialValue?: AppCategory;
   initialValue?: AppCategory;
 }
 }
 
 
-type OptionsType = { value: AppCategory; label: string };
+type OptionsType = { value: AppCategory; label: string; icon: Icon };
+
+const IconOption = (props: OptionProps<OptionsType>) => {
+  const { data } = props;
+  const { icon: CategoryIcon, label } = data;
+  return (
+    <Option {...props}>
+      <>
+        <CategoryIcon size={20} />
+        <span style={{ marginLeft: 10 }}>{label}</span>
+      </>
+    </Option>
+  );
+};
+
+const ControlComponent = (props: ControlProps<OptionsType>) => {
+  const { children, ...rest } = props;
+  const { getValue } = props;
+
+  const value = getValue()[0];
+
+  if (value?.icon) {
+    return (
+      <Control {...rest}>
+        <value.icon className="ms-2" size={20} />
+        {children}
+      </Control>
+    );
+  }
+
+  return <Control {...rest}> {children}</Control>;
+};
 
 
 const CategorySelector: React.FC<IProps> = ({ onSelect, className, initialValue }) => {
 const CategorySelector: React.FC<IProps> = ({ onSelect, className, initialValue }) => {
   const { darkMode } = useUIStore();
   const { darkMode } = useUIStore();
   const options: OptionsType[] = APP_CATEGORIES.map((category) => ({
   const options: OptionsType[] = APP_CATEGORIES.map((category) => ({
     value: category.id,
     value: category.id,
     label: category.name,
     label: category.name,
+    icon: category.icon,
   }));
   }));
 
 
   const [value, setValue] = React.useState<OptionsType | null>(options.find((o) => o.value === initialValue) || null);
   const [value, setValue] = React.useState<OptionsType | null>(options.find((o) => o.value === initialValue) || null);
@@ -63,6 +98,10 @@ const CategorySelector: React.FC<IProps> = ({ onSelect, className, initialValue
           fontSize: '0.8rem',
           fontSize: '0.8rem',
         }),
         }),
       }}
       }}
+      components={{
+        Option: IconOption,
+        Control: ControlComponent,
+      }}
       onChange={handleChange}
       onChange={handleChange}
       defaultValue={[]}
       defaultValue={[]}
       name="categories"
       name="categories"

+ 1 - 0
src/client/modules/AppStore/helpers/table.helpers.ts

@@ -45,4 +45,5 @@ export const colorSchemeForCategory: Record<AppCategory, string> = {
   music: 'cyan',
   music: 'cyan',
   finance: 'dark',
   finance: 'dark',
   gaming: 'pink',
   gaming: 'pink',
+  ai: 'gray',
 };
 };

+ 4 - 3
src/server/services/apps/apps.types.ts

@@ -9,7 +9,7 @@ export const APP_STATUS = {
   UPDATING: 'updating',
   UPDATING: 'updating',
 } as const;
 } as const;
 
 
-export type AppStatus = typeof APP_STATUS[keyof typeof APP_STATUS];
+export type AppStatus = (typeof APP_STATUS)[keyof typeof APP_STATUS];
 
 
 export const APP_CATEGORIES = {
 export const APP_CATEGORIES = {
   NETWORK: 'network',
   NETWORK: 'network',
@@ -26,9 +26,10 @@ export const APP_CATEGORIES = {
   MUSIC: 'music',
   MUSIC: 'music',
   FINANCE: 'finance',
   FINANCE: 'finance',
   GAMING: 'gaming',
   GAMING: 'gaming',
+  AI: 'ai',
 } as const;
 } as const;
 
 
-export type AppCategory = typeof APP_CATEGORIES[keyof typeof APP_CATEGORIES];
+export type AppCategory = (typeof APP_CATEGORIES)[keyof typeof APP_CATEGORIES];
 
 
 export const FIELD_TYPES = {
 export const FIELD_TYPES = {
   TEXT: 'text',
   TEXT: 'text',
@@ -42,4 +43,4 @@ export const FIELD_TYPES = {
   RANDOM: 'random',
   RANDOM: 'random',
 } as const;
 } as const;
 
 
-export type FieldType = typeof FIELD_TYPES[keyof typeof FIELD_TYPES];
+export type FieldType = (typeof FIELD_TYPES)[keyof typeof FIELD_TYPES];