Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adds search #401

Merged
merged 13 commits into from
Jul 12, 2022
13 changes: 11 additions & 2 deletions apps/hub-app/src/components/HomeDashboard.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { MouseEvent, useState, ChangeEvent } from 'react';
import { ITransformedMembership } from '@daohaus/dao-data';
import { ParMd, Spinner, useBreakpoint, widthQuery } from '@daohaus/ui';
import { MouseEvent, useState } from 'react';
import styled from 'styled-components';
import { ListType } from '../utils/appSpecificTypes';

import { DaoCards } from './DaoCards';
import { DaoTable } from './DaoTable';
import TableControl from './TableControl';
import { ListType } from '../utils/appSpecificTypes';

// Refactored this to be a component that we might be able to reuse
// for explore view and other similar views.
Expand All @@ -22,6 +23,8 @@ type DashProps = {
toggleDelegateFilter: (event: MouseEvent<HTMLButtonElement>) => void;
sortBy: string;
toggleSortBy: (event: MouseEvent<HTMLButtonElement>) => void;
searchTerm: string;
setSearchTerm: (event: ChangeEvent<HTMLInputElement>) => void;
loading: boolean;
};

Expand All @@ -33,6 +36,8 @@ export const HomeDashboard = ({
toggleDelegateFilter,
sortBy,
toggleSortBy,
searchTerm,
setSearchTerm,
loading,
}: DashProps) => {
const [listType, setListType] = useState<ListType>('cards');
Expand Down Expand Up @@ -76,6 +81,8 @@ export const HomeDashboard = ({
toggleDelegateFilter={toggleDelegateFilter}
sortBy={sortBy}
toggleSortBy={toggleSortBy}
searchTerm={searchTerm}
setSearchTerm={setSearchTerm}
/>
<NoDaosFound />
</Body>
Expand All @@ -93,6 +100,8 @@ export const HomeDashboard = ({
toggleDelegateFilter={toggleDelegateFilter}
sortBy={sortBy}
toggleSortBy={toggleSortBy}
searchTerm={searchTerm}
setSearchTerm={setSearchTerm}
/>
{isMobile ? (
<Mobile daoData={daoData} />
Expand Down
43 changes: 43 additions & 0 deletions apps/hub-app/src/components/SearchInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { ChangeEvent } from 'react';
import styled from 'styled-components';
import { indigoDark } from '@radix-ui/colors';
import { BiSearch } from 'react-icons/bi';
import { Input } from '@daohaus/ui';

const StyledInput = styled(Input)`
background: ${indigoDark.indigo3};
color: ${indigoDark.indigo11};
::placeholder {
color: ${indigoDark.indigo11};
}
:focus {
background: ${indigoDark.indigo3};
color: ${indigoDark.indigo11};
}
`;

const IconSearch = styled(BiSearch)`
fill: ${indigoDark.indigo11};
:hover {
fill: ${indigoDark.indigo11};
}
`;

type SearchInputProps = {
searchTerm: string;
setSearchTerm: (event: ChangeEvent<HTMLInputElement>) => void;
};

const SearchInput = ({ searchTerm, setSearchTerm }: SearchInputProps) => {
return (
<StyledInput
icon={IconSearch}
id="table-search"
placeholder="Search Daos"
onChange={setSearchTerm}
defaultValue={searchTerm}
/>
);
};

export default SearchInput;
4 changes: 2 additions & 2 deletions apps/hub-app/src/components/SortDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ const DropdownButton = styled(Button)`
}
`;

type FilterDropdownProps = {
type SortDropdownProps = {
sortBy: string;
toggleSortBy: (event: MouseEvent<HTMLButtonElement>) => void;
};

const SortDropdown = ({ sortBy, toggleSortBy }: FilterDropdownProps) => {
const SortDropdown = ({ sortBy, toggleSortBy }: SortDropdownProps) => {
const theme = useTheme();

return (
Expand Down
39 changes: 10 additions & 29 deletions apps/hub-app/src/components/TableControl.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { Button, Input, useBreakpoint, widthQuery } from '@daohaus/ui';
import { MouseEvent, ChangeEvent } from 'react';
import { Button, useBreakpoint, widthQuery } from '@daohaus/ui';
import styled from 'styled-components';
import { BiSearch } from 'react-icons/bi';
import { BsFillGrid3X3GapFill } from 'react-icons/bs';

import { indigoDark } from '@radix-ui/colors';
import { ListType } from '../utils/appSpecificTypes';
import { MouseEvent } from 'react';

import FilterDropdown from './FilterDropdown';
import SortDropdown from './SortDropdown';
import { ListType } from '../utils/appSpecificTypes';
import SearchInput from './SearchInput';

const IconGrid = styled(BsFillGrid3X3GapFill)`
height: 1.8rem;
Expand All @@ -19,13 +19,6 @@ const IconGrid = styled(BsFillGrid3X3GapFill)`
}
`;

const IconSearch = styled(BiSearch)`
fill: ${indigoDark.indigo11};
:hover {
fill: ${indigoDark.indigo11};
}
`;

const Layout = styled.div`
display: flex;
align-items: center;
Expand All @@ -38,18 +31,6 @@ const Layout = styled.div`
}
`;

const StyledInput = styled(Input)`
background: ${indigoDark.indigo3};
color: ${indigoDark.indigo11};
::placeholder {
color: ${indigoDark.indigo11};
}
:focus {
background: ${indigoDark.indigo3};
color: ${indigoDark.indigo11};
}
`;

type TableControlProps = {
listType: ListType;
toggleListType: () => void;
Expand All @@ -59,6 +40,8 @@ type TableControlProps = {
toggleDelegateFilter: (event: MouseEvent<HTMLButtonElement>) => void;
sortBy: string;
toggleSortBy: (event: MouseEvent<HTMLButtonElement>) => void;
searchTerm: string;
setSearchTerm: (event: ChangeEvent<HTMLInputElement>) => void;
};

const TableControl = ({
Expand All @@ -70,16 +53,14 @@ const TableControl = ({
toggleDelegateFilter,
sortBy,
toggleSortBy,
searchTerm,
setSearchTerm,
}: TableControlProps) => {
const isMobile = useBreakpoint(widthQuery.sm);

return (
<Layout>
<StyledInput
icon={IconSearch}
id="table-search"
placeholder="Search 3 Daos"
/>
<SearchInput searchTerm={searchTerm} setSearchTerm={setSearchTerm} />
<FilterDropdown
filterNetworks={filterNetworks}
toggleNetworkFilter={toggleNetworkFilter}
Expand Down
19 changes: 15 additions & 4 deletions apps/hub-app/src/pages/HomePage.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { MouseEvent, useEffect, useState } from 'react';
import { MouseEvent, ChangeEvent, useEffect, useState } from 'react';
import { indigoDark } from '@radix-ui/colors';
import styled from 'styled-components';

Expand All @@ -19,6 +19,7 @@ import {

import { getDelegateFilter } from '../utils/queryHelpers';
import { DEFAULT_SORT_KEY, SORT_FIELDS } from '../utils/constants';
import useDebounce from '../utils/debounceHook';

const Layout = styled.div`
width: 100%;
Expand Down Expand Up @@ -78,8 +79,11 @@ const HomePage = () => {
);
const [filterDelegate, setFilterDelegate] = useState<string | ''>('');
const [sortBy, setSortBy] = useState<string>(DEFAULT_SORT_KEY);
const [searchTerm, setSearchTerm] = useState<string | ''>('');
const [loading, setLoading] = useState<boolean>(true);

const debouncedSearchTerm = useDebounce<string>(searchTerm, 1000);

useEffect(() => {
const getDaos = async (address: string) => {
setLoading(true);
Expand All @@ -90,8 +94,7 @@ const HomePage = () => {
memberAddress: address,
networkIds: Object.keys(filterNetworks) as ValidNetwork[],
includeTokens: true,
// TODO: search filter will go here:
// daoFilter: { name_contains_nocase: 'carl' },
daoFilter: { name_contains_nocase: debouncedSearchTerm },
memberFilter: getDelegateFilter(filterDelegate, address),
ordering: SORT_FIELDS[sortBy].ordering,
});
Expand All @@ -110,7 +113,7 @@ const HomePage = () => {

if (!address) return;
getDaos(address);
}, [address, filterNetworks, filterDelegate, sortBy]);
}, [address, filterNetworks, filterDelegate, sortBy, debouncedSearchTerm]);

const toggleNetworkFilter = (event: MouseEvent<HTMLButtonElement>) => {
const network = event.currentTarget.value;
Expand Down Expand Up @@ -141,6 +144,12 @@ const HomePage = () => {
);
};

const handleSearchTermChange = (event: ChangeEvent<HTMLInputElement>) => {
setSearchTerm((prevState) =>
prevState === event.target.value ? '' : event.target.value
);
};

return (
<Layout>
<SideTopLeft />
Expand All @@ -159,6 +168,8 @@ const HomePage = () => {
toggleDelegateFilter={toggleDelegateFilter}
sortBy={sortBy}
toggleSortBy={toggleSortBy}
searchTerm={searchTerm}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad on all this prop threading.

We can restructure this once we reincorporate the layout elements.

setSearchTerm={handleSearchTermChange}
loading={loading}
/>
) : (
Expand Down
17 changes: 17 additions & 0 deletions apps/hub-app/src/utils/debounceHook.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { useEffect, useState } from 'react';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks nice and clean.


function useDebounce<T>(value: T, delay?: number): T {
const [debouncedValue, setDebouncedValue] = useState<T>(value);

useEffect(() => {
const timer = setTimeout(() => setDebouncedValue(value), delay || 500);

return () => {
clearTimeout(timer);
};
}, [value, delay]);

return debouncedValue;
}

export default useDebounce;
1 change: 1 addition & 0 deletions libs/ui/src/components/atoms/Input/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import React from 'react';

export type InputProps = Field & {
icon?: IconType;
onChange?: React.ChangeEventHandler<HTMLInputElement> | undefined;
className?: string;
};
type Ref =
Expand Down