Skip to content

Commit

Permalink
adds search (#401)
Browse files Browse the repository at this point in the history
* adds search wip

* correctly types the onChange for the input

* cleans up unsed imports

* naming

* Feature/public profile (#384)

* Add some stuff

* Add public profile

* Add ens

* Get build to pass

* Update apps/hub-app/src/pages/PublicProfilePage.tsx

Co-authored-by: Rowdy <[email protected]>

Co-authored-by: Sam Kuhlmann <[email protected]>
Co-authored-by: Rowdy <[email protected]>

* fixing doc display name from <[object Object]> to displayName (#402)

Co-authored-by: Sam Kuhlmann <[email protected]>

* conflicts

* correctly types the onChange for the input

* cleans up unsed imports

* naming

* fix build error

Co-authored-by: Alexander Keating <[email protected]>
Co-authored-by: Rowdy <[email protected]>
Co-authored-by: Brian Rossetti <[email protected]>
  • Loading branch information
4 people authored Jul 12, 2022
1 parent 5a64ccc commit 2c80dca
Show file tree
Hide file tree
Showing 12 changed files with 146 additions and 56 deletions.
9 changes: 2 additions & 7 deletions apps/hub-app/src/Routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,8 @@ import PublicProfilePage from './pages/PublicProfilePage';
const Routes = () => {
return (
<RoutesDom>
<Route path="/">
<Route path="dashboard" element={<HomePage />} />
<Route path="explore" element={<HomePage />} />
<Route path="profile">
<Route path=":address" element={<PublicProfilePage />} />
</Route>
</Route>
<Route path="/" element={<HomePage />} />
<Route path="profile/:address" element={<PublicProfilePage />} />
</RoutesDom>
);
};
Expand Down
5 changes: 0 additions & 5 deletions apps/hub-app/src/components/BodyNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,17 +79,12 @@ const NavLink = ({ children, path, selected }: NavLinkProps) => {
export const BodyNav = () => {
const match = useMatch('/explore');
const isHome = !match;
const isExplore = !!match;
return (
<BodyNavContainer>
<NavLink path="/" selected={isHome}>
<StyledHamburgerMenu />
Home
</NavLink>
<NavLink path="/explore" selected={isExplore}>
<StyledHamburgerMenu />
Explore
</NavLink>
</BodyNavContainer>
);
};
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
4 changes: 2 additions & 2 deletions apps/hub-app/src/components/Profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ const StyledLink = styled(Link)`
`;

export const HeaderProfile = () => {
const { profile } = useHausConnect();
const { profile, address } = useHausConnect();
return (
<ProfileContainer>
<StyledAvatar src={profile?.image || ''} size="lg" alt="profile image" />
Expand Down Expand Up @@ -117,7 +117,7 @@ export const HeaderProfile = () => {
{
type: 'clickable',
content: (
<StyledLink to="/">
<StyledLink to={`/profile/${address}`}>
<StyledParMd>View Public</StyledParMd>
</StyledLink>
),
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
1 change: 1 addition & 0 deletions apps/hub-app/src/hooks/useDaoData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useEffect, useState } from 'react';
import { useHausConnect } from '@daohaus/daohaus-connect-feature';
import { Haus, ITransformedMembership } from '@daohaus/dao-data';
import { networkData, ValidNetwork } from '@daohaus/common-utilities';
import useDebounce from '../utils/debounceHook';

const temporaryInitHaus = () => {
return Haus.create();
Expand Down
64 changes: 56 additions & 8 deletions apps/hub-app/src/pages/HomePage.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
import { MouseEvent, useState } from 'react';

import { MouseEvent, ChangeEvent, useEffect, useState } from 'react';
import { useHausConnect } from '@daohaus/daohaus-connect-feature';
import {
isValidNetwork,
networkData,
ValidNetwork,
} from '@daohaus/common-utilities';

import { Layout, SideTopLeft, SideTopRight } from '../components/Layout';
import ProfileArea from '../components/ProfileArea';
import Header from '../components/Header';
import { HomeDashboard } from '../components/HomeDashboard';
import useDaoData from '../hooks/useDaoData';
import { HomeNotConnected } from './HomeNotConnected';
import { isValidNetwork, networkData } from '@daohaus/common-utilities';

import { DEFAULT_SORT_KEY } from '../utils/constants';
import { getDelegateFilter } from '../utils/queryHelpers';
import { DEFAULT_SORT_KEY, SORT_FIELDS } from '../utils/constants';
import useDebounce from '../utils/debounceHook';
import { Haus, ITransformedMembership } from '@daohaus/dao-data';

const HomePage = () => {
const { isConnected } = useHausConnect();
const { daoData, isLoadingDaoData } = useDaoData();
const { isConnected, address } = useHausConnect();
const [daoData, setDaoData] = useState<ITransformedMembership[]>([]);
const [filterNetworks, setFilterNetworks] = useState<Record<string, string>>(
Object.keys(networkData).reduce(
(acc, networkId) => ({ ...acc, [networkId]: networkId }),
Expand All @@ -23,6 +28,41 @@ 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);
try {
const haus = Haus.create();

const query = await haus.profile.listDaosByMember({
memberAddress: address,
networkIds: Object.keys(filterNetworks) as ValidNetwork[],
includeTokens: true,
daoFilter: { name_contains_nocase: debouncedSearchTerm },
memberFilter: getDelegateFilter(filterDelegate, address),
ordering: SORT_FIELDS[sortBy].ordering,
});

if (query.data?.daos) {
setDaoData(query.data.daos);
}
} catch (error) {
error instanceof Error
? console.error(error.message)
: console.error('Well, shit...');
} finally {
setLoading(false);
}
};

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

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

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

return (
<Layout>
<SideTopLeft />
Expand All @@ -68,7 +114,9 @@ const HomePage = () => {
toggleDelegateFilter={toggleDelegateFilter}
sortBy={sortBy}
toggleSortBy={toggleSortBy}
loading={isLoadingDaoData}
searchTerm={searchTerm}
setSearchTerm={handleSearchTermChange}
loading={loading}
/>
) : (
<HomeNotConnected />
Expand Down
2 changes: 1 addition & 1 deletion apps/hub-app/src/pages/PublicProfilePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ const PublicProfilePage = () => {
) : (
<>
<BodyNavArea>
<StyledLink to="/dashboard">
<StyledLink to="/">
<Icon>
<StyledArrowLeft />
</Icon>
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';

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

0 comments on commit 2c80dca

Please sign in to comment.