Replace Fontawesome Pro by React-Icons/FA (#93)

* Fontawesome -> ReactIcons cleanup

* No need for npmrc anymore

* Complete migration

* Fix tests

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Félix Malfait
2023-05-03 17:24:07 +02:00
committed by GitHub
parent f28edd405f
commit 9bc3aa1fb9
30 changed files with 813 additions and 881 deletions

View File

@ -18,8 +18,7 @@ Twenty development stack is composed of 3 different layers
## Setup env variables and npmrc variables ## Setup env variables and npmrc variables
1. `cp ./infra/dev/.env.example ./infra/dev/.env` and fill with values `cp ./infra/dev/.env.example ./infra/dev/.env` and fill with values
2. `cp ./front/.npmrc.example ./front/.npmrc` and fill with values
## Development environment setup with docker-compose (Recommended) ## Development environment setup with docker-compose (Recommended)

View File

@ -1,2 +0,0 @@
@fortawesome:registry=https://npm.fontawesome.com/
//npm.fontawesome.com/:_authToken=REPLACE_ME

1402
front/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -6,10 +6,6 @@
"@apollo/client": "^3.7.5", "@apollo/client": "^3.7.5",
"@emotion/react": "^11.10.6", "@emotion/react": "^11.10.6",
"@emotion/styled": "^11.10.5", "@emotion/styled": "^11.10.5",
"@fortawesome/fontawesome-svg-core": "^6.2.1",
"@fortawesome/pro-regular-svg-icons": "^6.4.0",
"@fortawesome/pro-solid-svg-icons": "^6.4.0",
"@fortawesome/react-fontawesome": "^0.2.0",
"@tanstack/react-table": "^8.8.5", "@tanstack/react-table": "^8.8.5",
"@types/node": "^16.18.4", "@types/node": "^16.18.4",
"@types/react": "^18.0.25", "@types/react": "^18.0.25",
@ -20,6 +16,7 @@
"libphonenumber-js": "^1.10.26", "libphonenumber-js": "^1.10.26",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-icons": "^4.8.0",
"react-router-dom": "^6.4.4", "react-router-dom": "^6.4.4",
"web-vitals": "^2.1.4" "web-vitals": "^2.1.4"
}, },

View File

@ -1,10 +1,9 @@
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { ReactNode } from 'react';
import { IconProp } from '@fortawesome/fontawesome-svg-core';
type OwnProps = { type OwnProps = {
viewName: string; viewName: string;
viewIcon?: IconProp; viewIcon?: ReactNode;
}; };
const StyledTitle = styled.div` const StyledTitle = styled.div`
@ -24,7 +23,7 @@ const StyledIcon = styled.div`
function TableHeader({ viewName, viewIcon }: OwnProps) { function TableHeader({ viewName, viewIcon }: OwnProps) {
return ( return (
<StyledTitle> <StyledTitle>
<StyledIcon>{viewIcon && <FontAwesomeIcon icon={viewIcon} />}</StyledIcon> <StyledIcon>{viewIcon}</StyledIcon>
{viewName} {viewName}
</StyledTitle> </StyledTitle>
); );

View File

@ -7,7 +7,6 @@ import {
useReactTable, useReactTable,
} from '@tanstack/react-table'; } from '@tanstack/react-table';
import TableHeader from './table-header/TableHeader'; import TableHeader from './table-header/TableHeader';
import { IconProp } from '@fortawesome/fontawesome-svg-core';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { import {
FilterType, FilterType,
@ -19,7 +18,7 @@ type OwnProps<TData, SortField> = {
data: Array<TData>; data: Array<TData>;
columns: Array<ColumnDef<TData, any>>; columns: Array<ColumnDef<TData, any>>;
viewName: string; viewName: string;
viewIcon?: IconProp; viewIcon?: React.ReactNode;
onSortsUpdate?: (sorts: Array<SelectedSortType<SortField>>) => void; onSortsUpdate?: (sorts: Array<SelectedSortType<SortField>>) => void;
availableSorts?: Array<SortType<SortField>>; availableSorts?: Array<SortType<SortField>>;
availableFilters?: FilterType[]; availableFilters?: FilterType[];

View File

@ -2,8 +2,7 @@ import styled from '@emotion/styled';
import { useRef, ReactNode } from 'react'; import { useRef, ReactNode } from 'react';
import { useOutsideAlerter } from '../../../hooks/useOutsideAlerter'; import { useOutsideAlerter } from '../../../hooks/useOutsideAlerter';
import { modalBackground } from '../../../layout/styles/themes'; import { modalBackground } from '../../../layout/styles/themes';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FaAngleDown } from 'react-icons/fa';
import { faAngleDown } from '@fortawesome/pro-regular-svg-icons';
type OwnProps = { type OwnProps = {
label: string; label: string;
@ -183,7 +182,7 @@ const StyleAngleDownContainer = styled.div`
function DropdownTopOptionAngleDown() { function DropdownTopOptionAngleDown() {
return ( return (
<StyleAngleDownContainer> <StyleAngleDownContainer>
<FontAwesomeIcon icon={faAngleDown} /> <FaAngleDown />
</StyleAngleDownContainer> </StyleAngleDownContainer>
); );
} }

View File

@ -1,6 +1,5 @@
import { useCallback, useState } from 'react'; import { useCallback, useState } from 'react';
import DropdownButton from './DropdownButton'; import DropdownButton from './DropdownButton';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { FilterType, SelectedFilterType } from './interface'; import { FilterType, SelectedFilterType } from './interface';
type OwnProps = { type OwnProps = {
@ -72,9 +71,7 @@ export function FilterDropdownButton({
setSelectedFilter(filter); setSelectedFilter(filter);
}} }}
> >
<DropdownButton.StyledIcon> <DropdownButton.StyledIcon>{filter.icon}</DropdownButton.StyledIcon>
{filter.icon && <FontAwesomeIcon icon={filter.icon} />}
</DropdownButton.StyledIcon>
{filter.label} {filter.label}
</DropdownButton.StyledDropdownItem> </DropdownButton.StyledDropdownItem>
)); ));

View File

@ -1,6 +1,6 @@
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import SortOrFilterChip from './SortOrFilterChip'; import SortOrFilterChip from './SortOrFilterChip';
import { faArrowDown, faArrowUp } from '@fortawesome/pro-regular-svg-icons'; import { FaArrowDown, FaArrowUp } from 'react-icons/fa';
import { SelectedFilterType, SelectedSortType } from './interface'; import { SelectedFilterType, SelectedSortType } from './interface';
type OwnProps<SortField> = { type OwnProps<SortField> = {
@ -53,7 +53,7 @@ function SortAndFilterBar<SortField extends string>({
key={sort.key} key={sort.key}
labelValue={sort.label} labelValue={sort.label}
id={sort.key} id={sort.key}
icon={sort.order === 'asc' ? faArrowDown : faArrowUp} icon={sort.order === 'asc' ? <FaArrowDown /> : <FaArrowUp />}
onRemove={() => onRemoveSort(sort.key)} onRemove={() => onRemoveSort(sort.key)}
/> />
); );

View File

@ -1,7 +1,6 @@
import { useCallback, useState } from 'react'; import { useCallback, useState } from 'react';
import DropdownButton from './DropdownButton'; import DropdownButton from './DropdownButton';
import { SelectedSortType, SortType } from './interface'; import { SelectedSortType, SortType } from './interface';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
type OwnProps<SortField> = { type OwnProps<SortField> = {
sorts: SelectedSortType<SortField>[]; sorts: SelectedSortType<SortField>[];
@ -74,7 +73,7 @@ export function SortDropdownButton<SortField extends string>({
}} }}
> >
<DropdownButton.StyledIcon> <DropdownButton.StyledIcon>
{sort.icon && <FontAwesomeIcon icon={sort.icon} />} {sort.icon}
</DropdownButton.StyledIcon> </DropdownButton.StyledIcon>
{sort.label} {sort.label}
</DropdownButton.StyledDropdownItem> </DropdownButton.StyledDropdownItem>

View File

@ -1,13 +1,12 @@
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FaTimes } from 'react-icons/fa';
import { faTimes } from '@fortawesome/pro-regular-svg-icons'; import { ReactNode } from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
type OwnProps = { type OwnProps = {
id: string; id: string;
labelKey?: string; labelKey?: string;
labelValue: string; labelValue: string;
icon: IconProp; icon: ReactNode;
onRemove: () => void; onRemove: () => void;
}; };
@ -44,13 +43,11 @@ function SortOrFilterChip({
}: OwnProps) { }: OwnProps) {
return ( return (
<StyledChip> <StyledChip>
<StyledIcon> <StyledIcon>{icon}</StyledIcon>
<FontAwesomeIcon icon={icon} />
</StyledIcon>
{labelKey && <StyledLabelKey>{labelKey}:&nbsp;</StyledLabelKey>} {labelKey && <StyledLabelKey>{labelKey}:&nbsp;</StyledLabelKey>}
{labelValue} {labelValue}
<StyledDelete onClick={onRemove} data-testid={'remove-icon-' + id}> <StyledDelete onClick={onRemove} data-testid={'remove-icon-' + id}>
<FontAwesomeIcon icon={faTimes} /> <FaTimes />
</StyledDelete> </StyledDelete>
</StyledChip> </StyledChip>
); );

View File

@ -1,21 +1,19 @@
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import DropdownButton from './DropdownButton'; import DropdownButton from './DropdownButton';
import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { import {
FilterType, FilterType,
SelectedFilterType, SelectedFilterType,
SelectedSortType, SelectedSortType,
SortType, SortType,
} from './interface'; } from './interface';
import { useCallback, useState } from 'react'; import { ReactNode, useCallback, useState } from 'react';
import { SortDropdownButton } from './SortDropdownButton'; import { SortDropdownButton } from './SortDropdownButton';
import { FilterDropdownButton } from './FilterDropdownButton'; import { FilterDropdownButton } from './FilterDropdownButton';
import SortAndFilterBar from './SortAndFilterBar'; import SortAndFilterBar from './SortAndFilterBar';
type OwnProps<SortField> = { type OwnProps<SortField> = {
viewName: string; viewName: string;
viewIcon?: IconProp; viewIcon?: ReactNode;
onSortsUpdate?: (sorts: Array<SelectedSortType<SortField>>) => void; onSortsUpdate?: (sorts: Array<SelectedSortType<SortField>>) => void;
onFiltersUpdate?: (sorts: Array<SelectedFilterType>) => void; onFiltersUpdate?: (sorts: Array<SelectedFilterType>) => void;
availableSorts?: Array<SortType<SortField>>; availableSorts?: Array<SortType<SortField>>;
@ -110,9 +108,7 @@ function TableHeader<SortField extends string>({
<StyledContainer> <StyledContainer>
<StyledTableHeader> <StyledTableHeader>
<StyledViewSection> <StyledViewSection>
<StyledIcon> <StyledIcon>{viewIcon}</StyledIcon>
{viewIcon && <FontAwesomeIcon icon={viewIcon} />}
</StyledIcon>
{viewName} {viewName}
</StyledViewSection> </StyledViewSection>
<StyledFilters> <StyledFilters>

View File

@ -4,13 +4,13 @@ import { FilterDropdownButton } from '../FilterDropdownButton';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { FilterType, SelectedFilterType } from '../interface'; import { FilterType, SelectedFilterType } from '../interface';
import { import {
faUser, FaRegUser,
faBuildings, FaRegBuilding,
faEnvelope, FaEnvelope,
faPhone, FaPhone,
faCalendar, FaCalendar,
faMapPin, FaMapPin,
} from '@fortawesome/pro-regular-svg-icons'; } from 'react-icons/fa';
import { useCallback, useState } from 'react'; import { useCallback, useState } from 'react';
const component = { const component = {
@ -28,25 +28,25 @@ const availableFilters = [
{ {
key: 'fullname', key: 'fullname',
label: 'People', label: 'People',
icon: faUser, icon: <FaRegUser />,
}, },
{ {
key: 'company_name', key: 'company_name',
label: 'Company', label: 'Company',
icon: faBuildings, icon: <FaRegBuilding />,
}, },
{ {
key: 'email', key: 'email',
label: 'Email', label: 'Email',
icon: faEnvelope, icon: <FaEnvelope />,
}, },
{ key: 'phone', label: 'Phone', icon: faPhone }, { key: 'phone', label: 'Phone', icon: <FaPhone /> },
{ {
key: 'created_at', key: 'created_at',
label: 'Created at', label: 'Created at',
icon: faCalendar, icon: <FaCalendar />,
}, },
{ key: 'city', label: 'City', icon: faMapPin }, { key: 'city', label: 'City', icon: <FaMapPin /> },
] satisfies FilterType[]; ] satisfies FilterType[];
const StyleDiv = styled.div` const StyleDiv = styled.div`

View File

@ -1,7 +1,7 @@
import SortAndFilterBar from '../SortAndFilterBar'; import SortAndFilterBar from '../SortAndFilterBar';
import { ThemeProvider } from '@emotion/react'; import { ThemeProvider } from '@emotion/react';
import { lightTheme } from '../../../../layout/styles/themes'; import { lightTheme } from '../../../../layout/styles/themes';
import { faArrowDown } from '@fortawesome/pro-regular-svg-icons'; import { FaArrowDown } from 'react-icons/fa';
const component = { const component = {
title: 'SortAndFilterBar', title: 'SortAndFilterBar',
@ -23,13 +23,13 @@ export const RegularSortAndFilterBar = ({ removeFunction }: OwnProps) => {
label: 'Test sort', label: 'Test sort',
order: 'asc', order: 'asc',
key: 'test_sort', key: 'test_sort',
icon: faArrowDown, icon: <FaArrowDown />,
}, },
{ {
label: 'Test sort 2', label: 'Test sort 2',
order: 'desc', order: 'desc',
key: 'test_sort_2', key: 'test_sort_2',
icon: faArrowDown, icon: <FaArrowDown />,
}, },
]} ]}
onRemoveSort={removeFunction} onRemoveSort={removeFunction}
@ -39,7 +39,7 @@ export const RegularSortAndFilterBar = ({ removeFunction }: OwnProps) => {
label: 'People', label: 'People',
operand: { id: 'include', label: 'Include' }, operand: { id: 'include', label: 'Include' },
id: 'test_filter', id: 'test_filter',
icon: faArrowDown, icon: <FaArrowDown />,
value: 'John Doe', value: 'John Doe',
}, },
]} ]}

View File

@ -2,13 +2,13 @@ import { SelectedSortType, SortType } from '../interface';
import { ThemeProvider } from '@emotion/react'; import { ThemeProvider } from '@emotion/react';
import { lightTheme } from '../../../../layout/styles/themes'; import { lightTheme } from '../../../../layout/styles/themes';
import { import {
faBuildings, FaRegBuilding,
faCalendar, FaCalendar,
faEnvelope, FaEnvelope,
faMapPin, FaMapPin,
faPhone, FaPhone,
faUser, FaRegUser,
} from '@fortawesome/pro-regular-svg-icons'; } from 'react-icons/fa';
import { SortDropdownButton } from '../SortDropdownButton'; import { SortDropdownButton } from '../SortDropdownButton';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
@ -29,25 +29,25 @@ const availableSorts = [
{ {
key: 'fullname', key: 'fullname',
label: 'People', label: 'People',
icon: faUser, icon: <FaRegUser />,
}, },
{ {
key: 'company_name', key: 'company_name',
label: 'Company', label: 'Company',
icon: faBuildings, icon: <FaRegBuilding />,
}, },
{ {
key: 'email', key: 'email',
label: 'Email', label: 'Email',
icon: faEnvelope, icon: <FaEnvelope />,
}, },
{ key: 'phone', label: 'Phone', icon: faPhone }, { key: 'phone', label: 'Phone', icon: <FaPhone /> },
{ {
key: 'created_at', key: 'created_at',
label: 'Created at', label: 'Created at',
icon: faCalendar, icon: <FaCalendar />,
}, },
{ key: 'city', label: 'City', icon: faMapPin }, { key: 'city', label: 'City', icon: <FaMapPin /> },
] satisfies SortType[]; ] satisfies SortType[];
const StyleDiv = styled.div` const StyleDiv = styled.div`

View File

@ -1,7 +1,7 @@
import SortOrFilterChip from '../SortOrFilterChip'; import SortOrFilterChip from '../SortOrFilterChip';
import { ThemeProvider } from '@emotion/react'; import { ThemeProvider } from '@emotion/react';
import { lightTheme } from '../../../../layout/styles/themes'; import { lightTheme } from '../../../../layout/styles/themes';
import { faArrowDown, faPeople } from '@fortawesome/pro-regular-svg-icons'; import { FaArrowDown, FaRegUser } from 'react-icons/fa';
const component = { const component = {
title: 'SortOrFilterChip', title: 'SortOrFilterChip',
@ -19,7 +19,7 @@ export const RegularFilterChip = ({ removeFunction }: OwnProps) => {
<ThemeProvider theme={lightTheme}> <ThemeProvider theme={lightTheme}>
<SortOrFilterChip <SortOrFilterChip
id="test_sort" id="test_sort"
icon={faPeople} icon={<FaRegUser />}
labelKey="Account owner" labelKey="Account owner"
labelValue="is Charles" labelValue="is Charles"
onRemove={removeFunction} onRemove={removeFunction}
@ -33,7 +33,7 @@ export const RegularSortChip = ({ removeFunction }: OwnProps) => {
<ThemeProvider theme={lightTheme}> <ThemeProvider theme={lightTheme}>
<SortOrFilterChip <SortOrFilterChip
id="test_sort" id="test_sort"
icon={faArrowDown} icon={<FaArrowDown />}
labelValue="Created at" labelValue="Created at"
onRemove={removeFunction} onRemove={removeFunction}
/> />

View File

@ -1,7 +1,7 @@
import TableHeader from '../TableHeader'; import TableHeader from '../TableHeader';
import { ThemeProvider } from '@emotion/react'; import { ThemeProvider } from '@emotion/react';
import { lightTheme } from '../../../../layout/styles/themes'; import { lightTheme } from '../../../../layout/styles/themes';
import { faBuilding, faCalendar } from '@fortawesome/pro-regular-svg-icons'; import { FaRegBuilding, FaCalendar } from 'react-icons/fa';
import { SortType } from '../interface'; import { SortType } from '../interface';
const component = { const component = {
@ -16,14 +16,14 @@ export const RegularTableHeader = () => {
{ {
key: 'created_at', key: 'created_at',
label: 'Created at', label: 'Created at',
icon: faCalendar, icon: <FaCalendar />,
}, },
]; ];
return ( return (
<ThemeProvider theme={lightTheme}> <ThemeProvider theme={lightTheme}>
<TableHeader <TableHeader
viewName="Test" viewName="Test"
viewIcon={faBuilding} viewIcon={<FaRegBuilding />}
availableSorts={availableSorts} availableSorts={availableSorts}
/> />
</ThemeProvider> </ThemeProvider>

View File

@ -1,6 +1,6 @@
import { fireEvent, render, waitFor } from '@testing-library/react'; import { fireEvent, render, waitFor } from '@testing-library/react';
import { RegularFilterDropdownButton } from '../__stories__/FilterDropdownButton.stories'; import { RegularFilterDropdownButton } from '../__stories__/FilterDropdownButton.stories';
import { faEnvelope } from '@fortawesome/pro-regular-svg-icons'; import { FaEnvelope } from 'react-icons/fa';
it('Checks the default top option is Include', async () => { it('Checks the default top option is Include', async () => {
const setSorts = jest.fn(); const setSorts = jest.fn();
@ -23,7 +23,7 @@ it('Checks the default top option is Include', async () => {
value: 'John Doe', value: 'John Doe',
label: 'Email', label: 'Email',
operand: { id: 'include', label: 'Include' }, operand: { id: 'include', label: 'Include' },
icon: faEnvelope, icon: <FaEnvelope />,
}, },
]); ]);
}); });
@ -55,7 +55,7 @@ it('Checks the selection of top option for Doesnot include', async () => {
value: 'John Doe', value: 'John Doe',
label: 'Email', label: 'Email',
operand: { id: 'not-include', label: "Doesn't include" }, operand: { id: 'not-include', label: "Doesn't include" },
icon: faEnvelope, icon: <FaEnvelope />,
}, },
]); ]);

View File

@ -1,6 +1,6 @@
import { fireEvent, render } from '@testing-library/react'; import { fireEvent, render } from '@testing-library/react';
import { RegularSortDropdownButton } from '../__stories__/SortDropdownButton.stories'; import { RegularSortDropdownButton } from '../__stories__/SortDropdownButton.stories';
import { faEnvelope } from '@fortawesome/pro-regular-svg-icons'; import { FaEnvelope } from 'react-icons/fa';
it('Checks the default top option is Ascending', async () => { it('Checks the default top option is Ascending', async () => {
const setSorts = jest.fn(); const setSorts = jest.fn();
@ -18,7 +18,7 @@ it('Checks the default top option is Ascending', async () => {
{ {
label: 'Email', label: 'Email',
key: 'email', key: 'email',
icon: faEnvelope, icon: <FaEnvelope />,
order: 'asc', order: 'asc',
}, },
]); ]);
@ -46,7 +46,7 @@ it('Checks the selection of Descending', async () => {
{ {
label: 'Email', label: 'Email',
key: 'email', key: 'email',
icon: faEnvelope, icon: <FaEnvelope />,
order: 'desc', order: 'desc',
}, },
]); ]);

View File

@ -1,15 +1,15 @@
import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { ReactNode } from 'react';
export type SortType<SortKey = string> = { export type SortType<SortKey = string> = {
label: string; label: string;
key: SortKey; key: SortKey;
icon?: IconProp; icon?: ReactNode;
}; };
export type FilterType<FilterKey = string> = { export type FilterType<FilterKey = string> = {
label: string; label: string;
key: FilterKey; key: FilterKey;
icon: IconProp; icon: ReactNode;
}; };
export type SelectedFilterType = { export type SelectedFilterType = {
@ -17,7 +17,7 @@ export type SelectedFilterType = {
label: string; label: string;
value: string; value: string;
operand: { id: string; label: string }; operand: { id: string; label: string };
icon: IconProp; icon: ReactNode;
}; };
export type SelectedSortType<SortField = string> = SortType<SortField> & { export type SelectedSortType<SortField = string> = SortType<SortField> & {

View File

@ -1,11 +1,11 @@
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import TopBar from '../top-bar/TopBar'; import TopBar from '../top-bar/TopBar';
import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { ReactNode } from 'react';
type OwnProps = { type OwnProps = {
children: JSX.Element; children: JSX.Element;
title: string; title: string;
icon: IconProp; icon: ReactNode;
}; };
const StyledContainer = styled.div` const StyledContainer = styled.div`

View File

@ -1,13 +1,12 @@
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { ReactNode } from 'react';
import { IconProp } from '@fortawesome/fontawesome-svg-core';
type OwnProps = { type OwnProps = {
label: string; label: string;
to: string; to: string;
active?: boolean; active?: boolean;
icon: IconProp; icon: ReactNode;
}; };
type StyledItemProps = { type StyledItemProps = {
@ -50,7 +49,7 @@ function NavItem({ label, icon, to, active }: OwnProps) {
active={active} active={active}
aria-selected={active} aria-selected={active}
> >
<FontAwesomeIcon icon={icon} /> {icon}
<StyledItemLabel>{label}</StyledItemLabel> <StyledItemLabel>{label}</StyledItemLabel>
</StyledItem> </StyledItem>
); );

View File

@ -5,11 +5,7 @@ import { Workspace } from '../../interfaces/workspace.interface';
import NavItem from './NavItem'; import NavItem from './NavItem';
import NavTitle from './NavTitle'; import NavTitle from './NavTitle';
import WorkspaceContainer from './WorkspaceContainer'; import WorkspaceContainer from './WorkspaceContainer';
import { faUser } from '@fortawesome/pro-regular-svg-icons'; import { FaRegUser, FaRegBuilding, FaBullseye } from 'react-icons/fa';
import {
faBuildings,
faBullseyeArrow,
} from '@fortawesome/pro-regular-svg-icons';
const NavbarContainer = styled.div` const NavbarContainer = styled.div`
display: flex; display: flex;
@ -40,7 +36,7 @@ function Navbar({ workspace }: OwnProps) {
<NavItem <NavItem
label="People" label="People"
to="/people" to="/people"
icon={faUser} icon={<FaRegUser />}
active={ active={
!!useMatch({ !!useMatch({
path: useResolvedPath('/people').pathname, path: useResolvedPath('/people').pathname,
@ -51,7 +47,7 @@ function Navbar({ workspace }: OwnProps) {
<NavItem <NavItem
label="Companies" label="Companies"
to="/companies" to="/companies"
icon={faBuildings} icon={<FaRegBuilding />}
active={ active={
!!useMatch({ !!useMatch({
path: useResolvedPath('/companies').pathname, path: useResolvedPath('/companies').pathname,
@ -62,7 +58,7 @@ function Navbar({ workspace }: OwnProps) {
<NavItem <NavItem
label="Opportunities" label="Opportunities"
to="/opportunities" to="/opportunities"
icon={faBullseyeArrow} icon={<FaBullseye />}
active={ active={
!!useMatch({ !!useMatch({
path: useResolvedPath('/opportunities').pathname, path: useResolvedPath('/opportunities').pathname,

View File

@ -1,5 +1,5 @@
import { MemoryRouter } from 'react-router-dom'; import { MemoryRouter } from 'react-router-dom';
import { faUser } from '@fortawesome/pro-regular-svg-icons'; import { FaRegUser } from 'react-icons/fa';
import { ThemeProvider } from '@emotion/react'; import { ThemeProvider } from '@emotion/react';
import NavItem from '../../../layout/navbar/NavItem'; import NavItem from '../../../layout/navbar/NavItem';
@ -15,7 +15,7 @@ export default component;
export const NavItemDefault = () => ( export const NavItemDefault = () => (
<ThemeProvider theme={lightTheme}> <ThemeProvider theme={lightTheme}>
<MemoryRouter> <MemoryRouter>
<NavItem label="Test" to="/test" icon={faUser} /> <NavItem label="Test" to="/test" icon={<FaRegUser />} />
</MemoryRouter> </MemoryRouter>
</ThemeProvider> </ThemeProvider>
); );
@ -23,7 +23,7 @@ export const NavItemDefault = () => (
export const NavItemActive = () => ( export const NavItemActive = () => (
<ThemeProvider theme={lightTheme}> <ThemeProvider theme={lightTheme}>
<MemoryRouter initialEntries={['/test']}> <MemoryRouter initialEntries={['/test']}>
<NavItem label="Test" to="/test" active={true} icon={faUser} /> <NavItem label="Test" to="/test" active={true} icon={<FaRegUser />} />
</MemoryRouter> </MemoryRouter>
</ThemeProvider> </ThemeProvider>
); );

View File

@ -1,6 +1,5 @@
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { ReactNode } from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
const TopBarContainer = styled.div` const TopBarContainer = styled.div`
display: flex; display: flex;
@ -22,14 +21,14 @@ const TitleContainer = styled.div`
type OwnProps = { type OwnProps = {
title: string; title: string;
icon: IconProp; icon: ReactNode;
}; };
function TopBar({ title, icon }: OwnProps) { function TopBar({ title, icon }: OwnProps) {
return ( return (
<> <>
<TopBarContainer> <TopBarContainer>
<FontAwesomeIcon icon={icon} /> {icon}
<TitleContainer data-testid="top-bar-title">{title}</TitleContainer> <TitleContainer data-testid="top-bar-title">{title}</TitleContainer>
</TopBarContainer> </TopBarContainer>
</> </>

View File

@ -1,4 +1,4 @@
import { faBuildings, faList } from '@fortawesome/pro-regular-svg-icons'; import { FaRegBuilding, FaList } from 'react-icons/fa';
import WithTopBarContainer from '../../layout/containers/WithTopBarContainer'; import WithTopBarContainer from '../../layout/containers/WithTopBarContainer';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { useState, useCallback } from 'react'; import { useState, useCallback } from 'react';
@ -29,13 +29,13 @@ function Companies() {
const { data } = useCompaniesQuery(orderBy); const { data } = useCompaniesQuery(orderBy);
return ( return (
<WithTopBarContainer title="Companies" icon={faBuildings}> <WithTopBarContainer title="Companies" icon={<FaRegBuilding />}>
<StyledCompaniesContainer> <StyledCompaniesContainer>
<Table <Table
data={data ? data.companies.map(mapCompany) : []} data={data ? data.companies.map(mapCompany) : []}
columns={companiesColumns} columns={companiesColumns}
viewName="All Companies" viewName="All Companies"
viewIcon={faList} viewIcon={<FaList />}
onSortsUpdate={updateSorts} onSortsUpdate={updateSorts}
availableSorts={sortsAvailable} availableSorts={sortsAvailable}
/> />

View File

@ -8,14 +8,14 @@ import CompanyChip from '../../components/chips/CompanyChip';
import EditableCell from '../../components/table/EditableCell'; import EditableCell from '../../components/table/EditableCell';
import PipeChip from '../../components/chips/PipeChip'; import PipeChip from '../../components/chips/PipeChip';
import { import {
faBuildings, FaRegBuilding,
faCalendar, FaCalendar,
faLinkSimple, FaLink,
faMapPin, FaMapPin,
faRectangleHistory, FaStream,
faSigma, FaRegUser,
faUser, FaUsers,
} from '@fortawesome/pro-regular-svg-icons'; } from 'react-icons/fa';
import ClickableCell from '../../components/table/ClickableCell'; import ClickableCell from '../../components/table/ClickableCell';
import PersonChip from '../../components/chips/PersonChip'; import PersonChip from '../../components/chips/PersonChip';
import { SortType } from '../../components/table/table-header/interface'; import { SortType } from '../../components/table/table-header/interface';
@ -36,7 +36,7 @@ export const sortsAvailable = [
const columnHelper = createColumnHelper<Company>(); const columnHelper = createColumnHelper<Company>();
export const companiesColumns = [ export const companiesColumns = [
columnHelper.accessor('name', { columnHelper.accessor('name', {
header: () => <ColumnHead viewName="Name" viewIcon={faBuildings} />, header: () => <ColumnHead viewName="Name" viewIcon={<FaRegBuilding />} />,
cell: (props) => ( cell: (props) => (
<HorizontalyAlignedContainer> <HorizontalyAlignedContainer>
<Checkbox <Checkbox
@ -51,7 +51,7 @@ export const companiesColumns = [
), ),
}), }),
columnHelper.accessor('employees', { columnHelper.accessor('employees', {
header: () => <ColumnHead viewName="Employees" viewIcon={faSigma} />, header: () => <ColumnHead viewName="Employees" viewIcon={<FaUsers />} />,
cell: (props) => ( cell: (props) => (
<EditableCell <EditableCell
content={props.row.original.employees.toFixed(0)} content={props.row.original.employees.toFixed(0)}
@ -64,7 +64,7 @@ export const companiesColumns = [
), ),
}), }),
columnHelper.accessor('domain_name', { columnHelper.accessor('domain_name', {
header: () => <ColumnHead viewName="URL" viewIcon={faLinkSimple} />, header: () => <ColumnHead viewName="URL" viewIcon={<FaLink />} />,
cell: (props) => ( cell: (props) => (
<EditableCell <EditableCell
content={props.row.original.domain_name} content={props.row.original.domain_name}
@ -77,7 +77,7 @@ export const companiesColumns = [
), ),
}), }),
columnHelper.accessor('address', { columnHelper.accessor('address', {
header: () => <ColumnHead viewName="Address" viewIcon={faMapPin} />, header: () => <ColumnHead viewName="Address" viewIcon={<FaMapPin />} />,
cell: (props) => ( cell: (props) => (
<EditableCell <EditableCell
content={props.row.original.address} content={props.row.original.address}
@ -91,7 +91,7 @@ export const companiesColumns = [
}), }),
columnHelper.accessor('opportunities', { columnHelper.accessor('opportunities', {
header: () => ( header: () => (
<ColumnHead viewName="Opportunities" viewIcon={faRectangleHistory} /> <ColumnHead viewName="Opportunities" viewIcon={<FaStream />} />
), ),
cell: (props) => ( cell: (props) => (
<ClickableCell href="#"> <ClickableCell href="#">
@ -102,7 +102,7 @@ export const companiesColumns = [
), ),
}), }),
columnHelper.accessor('creationDate', { columnHelper.accessor('creationDate', {
header: () => <ColumnHead viewName="Creation" viewIcon={faCalendar} />, header: () => <ColumnHead viewName="Creation" viewIcon={<FaCalendar />} />,
cell: (props) => ( cell: (props) => (
<ClickableCell href="#"> <ClickableCell href="#">
{new Intl.DateTimeFormat(undefined, { {new Intl.DateTimeFormat(undefined, {
@ -114,7 +114,9 @@ export const companiesColumns = [
), ),
}), }),
columnHelper.accessor('accountOwner', { columnHelper.accessor('accountOwner', {
header: () => <ColumnHead viewName="Account Owner" viewIcon={faUser} />, header: () => (
<ColumnHead viewName="Account Owner" viewIcon={<FaRegUser />} />
),
cell: (props) => ( cell: (props) => (
<ClickableCell href="#"> <ClickableCell href="#">
<> <>

View File

@ -1,9 +1,9 @@
import { faBullseyeArrow } from '@fortawesome/pro-regular-svg-icons'; import { FaBullseye } from 'react-icons/fa';
import WithTopBarContainer from '../../layout/containers/WithTopBarContainer'; import WithTopBarContainer from '../../layout/containers/WithTopBarContainer';
function Opportunities() { function Opportunities() {
return ( return (
<WithTopBarContainer title="Opportunities" icon={faBullseyeArrow}> <WithTopBarContainer title="Opportunities" icon={<FaBullseye />}>
<></> <></>
</WithTopBarContainer> </WithTopBarContainer>
); );

View File

@ -1,4 +1,4 @@
import { faUser, faList } from '@fortawesome/pro-regular-svg-icons'; import { FaRegUser, FaList } from 'react-icons/fa';
import WithTopBarContainer from '../../layout/containers/WithTopBarContainer'; import WithTopBarContainer from '../../layout/containers/WithTopBarContainer';
import Table from '../../components/table/Table'; import Table from '../../components/table/Table';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
@ -34,14 +34,14 @@ function People() {
const { data } = usePeopleQuery(orderBy); const { data } = usePeopleQuery(orderBy);
return ( return (
<WithTopBarContainer title="People" icon={faUser}> <WithTopBarContainer title="People" icon={<FaRegUser />}>
<StyledPeopleContainer> <StyledPeopleContainer>
{ {
<Table <Table
data={data ? data.people.map(mapPerson) : []} data={data ? data.people.map(mapPerson) : []}
columns={peopleColumns} columns={peopleColumns}
viewName="All People" viewName="All People"
viewIcon={faList} viewIcon={<FaList />}
onSortsUpdate={updateSorts} onSortsUpdate={updateSorts}
availableSorts={availableSorts} availableSorts={availableSorts}
availableFilters={availableFilters} availableFilters={availableFilters}

View File

@ -1,12 +1,12 @@
import { import {
faBuildings, FaRegBuilding,
faCalendar, FaCalendar,
faEnvelope, FaEnvelope,
faUser, FaRegUser,
faMapPin, FaMapPin,
faPhone, FaPhone,
faRectangleHistory, FaStream,
} from '@fortawesome/pro-regular-svg-icons'; } from 'react-icons/fa';
import { createColumnHelper } from '@tanstack/react-table'; import { createColumnHelper } from '@tanstack/react-table';
import ClickableCell from '../../components/table/ClickableCell'; import ClickableCell from '../../components/table/ClickableCell';
import ColumnHead from '../../components/table/ColumnHead'; import ColumnHead from '../../components/table/ColumnHead';
@ -28,56 +28,56 @@ export const availableSorts = [
{ {
key: 'fullname', key: 'fullname',
label: 'People', label: 'People',
icon: faUser, icon: <FaRegUser />,
}, },
{ {
key: 'company_name', key: 'company_name',
label: 'Company', label: 'Company',
icon: faBuildings, icon: <FaRegBuilding />,
}, },
{ {
key: 'email', key: 'email',
label: 'Email', label: 'Email',
icon: faEnvelope, icon: <FaEnvelope />,
}, },
{ key: 'phone', label: 'Phone', icon: faPhone }, { key: 'phone', label: 'Phone', icon: <FaPhone /> },
{ {
key: 'created_at', key: 'created_at',
label: 'Created at', label: 'Created at',
icon: faCalendar, icon: <FaCalendar />,
}, },
{ key: 'city', label: 'City', icon: faMapPin }, { key: 'city', label: 'City', icon: <FaMapPin /> },
] satisfies Array<SortType<OrderByFields>>; ] satisfies Array<SortType<OrderByFields>>;
export const availableFilters = [ export const availableFilters = [
{ {
key: 'fullname', key: 'fullname',
label: 'People', label: 'People',
icon: faUser, icon: <FaRegUser />,
}, },
{ {
key: 'company_name', key: 'company_name',
label: 'Company', label: 'Company',
icon: faBuildings, icon: <FaRegBuilding />,
}, },
{ {
key: 'email', key: 'email',
label: 'Email', label: 'Email',
icon: faEnvelope, icon: <FaEnvelope />,
}, },
{ key: 'phone', label: 'Phone', icon: faPhone }, { key: 'phone', label: 'Phone', icon: <FaPhone /> },
{ {
key: 'created_at', key: 'created_at',
label: 'Created at', label: 'Created at',
icon: faCalendar, icon: <FaCalendar />,
}, },
{ key: 'city', label: 'City', icon: faMapPin }, { key: 'city', label: 'City', icon: <FaMapPin /> },
] satisfies FilterType[]; ] satisfies FilterType[];
const columnHelper = createColumnHelper<Person>(); const columnHelper = createColumnHelper<Person>();
export const peopleColumns = [ export const peopleColumns = [
columnHelper.accessor('fullName', { columnHelper.accessor('fullName', {
header: () => <ColumnHead viewName="People" viewIcon={faUser} />, header: () => <ColumnHead viewName="People" viewIcon={<FaRegUser />} />,
cell: (props) => ( cell: (props) => (
<> <>
<HorizontalyAlignedContainer> <HorizontalyAlignedContainer>
@ -94,7 +94,7 @@ export const peopleColumns = [
), ),
}), }),
columnHelper.accessor('email', { columnHelper.accessor('email', {
header: () => <ColumnHead viewName="Email" viewIcon={faEnvelope} />, header: () => <ColumnHead viewName="Email" viewIcon={<FaEnvelope />} />,
cell: (props) => ( cell: (props) => (
<EditableCell <EditableCell
content={props.row.original.email} content={props.row.original.email}
@ -107,7 +107,9 @@ export const peopleColumns = [
), ),
}), }),
columnHelper.accessor('company', { columnHelper.accessor('company', {
header: () => <ColumnHead viewName="Company" viewIcon={faBuildings} />, header: () => (
<ColumnHead viewName="Company" viewIcon={<FaRegBuilding />} />
),
cell: (props) => ( cell: (props) => (
<ClickableCell href="#"> <ClickableCell href="#">
<CompanyChip <CompanyChip
@ -118,7 +120,7 @@ export const peopleColumns = [
), ),
}), }),
columnHelper.accessor('phone', { columnHelper.accessor('phone', {
header: () => <ColumnHead viewName="Phone" viewIcon={faPhone} />, header: () => <ColumnHead viewName="Phone" viewIcon={<FaPhone />} />,
cell: (props) => ( cell: (props) => (
<ClickableCell <ClickableCell
href={parsePhoneNumber( href={parsePhoneNumber(
@ -134,7 +136,7 @@ export const peopleColumns = [
), ),
}), }),
columnHelper.accessor('creationDate', { columnHelper.accessor('creationDate', {
header: () => <ColumnHead viewName="Creation" viewIcon={faCalendar} />, header: () => <ColumnHead viewName="Creation" viewIcon={<FaCalendar />} />,
cell: (props) => ( cell: (props) => (
<ClickableCell href="#"> <ClickableCell href="#">
{new Intl.DateTimeFormat(undefined, { {new Intl.DateTimeFormat(undefined, {
@ -146,7 +148,7 @@ export const peopleColumns = [
), ),
}), }),
columnHelper.accessor('pipe', { columnHelper.accessor('pipe', {
header: () => <ColumnHead viewName="Pipe" viewIcon={faRectangleHistory} />, header: () => <ColumnHead viewName="Pipe" viewIcon={<FaStream />} />,
cell: (props) => ( cell: (props) => (
<ClickableCell href="#"> <ClickableCell href="#">
<PipeChip <PipeChip
@ -157,7 +159,7 @@ export const peopleColumns = [
), ),
}), }),
columnHelper.accessor('city', { columnHelper.accessor('city', {
header: () => <ColumnHead viewName="City" viewIcon={faMapPin} />, header: () => <ColumnHead viewName="City" viewIcon={<FaMapPin />} />,
cell: (props) => ( cell: (props) => (
<ClickableCell href="#">{props.row.original.city}</ClickableCell> <ClickableCell href="#">{props.row.original.city}</ClickableCell>
), ),