From 28608831a4a3d2276d1ce6364bddf9708b5d1eaa Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Sun, 27 Feb 2022 16:45:23 -0500 Subject: [PATCH] Start trying to piece together a more advanced search bar --- .../components/admin/users/UsersContainer.tsx | 43 ++++++++++++++++--- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/resources/scripts/components/admin/users/UsersContainer.tsx b/resources/scripts/components/admin/users/UsersContainer.tsx index 8a37813d3..835a6d8c4 100644 --- a/resources/scripts/components/admin/users/UsersContainer.tsx +++ b/resources/scripts/components/admin/users/UsersContainer.tsx @@ -1,4 +1,4 @@ -import React, { Fragment, useEffect, useState } from 'react'; +import React, { Fragment, useCallback, useEffect, useState } from 'react'; import http, { FractalPaginatedResponse, PaginatedResult, @@ -16,12 +16,16 @@ import { Checkbox, InputField } from '@/components/elements/inputs'; import UserTableRow from '@/components/admin/users/UserTableRow'; import useSWR, { SWRConfiguration, SWRResponse } from 'swr'; import { AxiosError } from 'axios'; +import debounce from 'debounce'; + +const filters = [ 'id', 'uuid', 'external_id', 'username', 'email' ] as const; +type Filters = typeof filters[number]; const useGetUsers = ( - params?: QueryBuilderParams<'id' | 'email' | 'uuid'>, + params?: QueryBuilderParams, config?: SWRConfiguration, ): SWRResponse, AxiosError> => { - return useSWR>([ '/api/application/users', params ], async () => { + return useSWR>([ '/api/application/users', JSON.stringify(params) ], async () => { const { data } = await http.get( '/api/application/users', { params: withQueryBuilderParams(params) }, @@ -40,7 +44,7 @@ const PaginationFooter = ({ pagination, span }: { span: number; pagination: Pagi

- Showing {Math.max(start, 1)} to  + Showing {Math.max(start, Math.min(pagination.total, 1))} to  {end} of  {pagination.total} results.

@@ -50,9 +54,33 @@ const PaginationFooter = ({ pagination, span }: { span: number; pagination: Pagi ); }; +const extractFiltersFromString = (str: string, params: (keyof Filters)[]): QueryBuilderParams => { + const filters: Partial> = {}; + + const parts = str.split(' '); + for (const segment of parts) { + const [ filter, value ] = segment.split(':', 2); + // @ts-ignore + if (!filter || !value || !params.includes(filter)) { + continue; + } + + const key = filter as string; + filters[key] = [ ...(filters[key] || []), value ]; + } + + if (!Object.keys(filters).length) { + return { filters: { email: str } }; + } + + // @ts-ignore + return { filters }; +}; + const UsersContainer = () => { - const { data: users } = useGetUsers(); + const [ search, setSearch ] = useState(''); const [ selected, setSelected ] = useState([]); + const { data: users } = useGetUsers(extractFiltersFromString(search, filters as unknown as (keyof Filters)[])); useEffect(() => { document.title = 'Admin | Users'; @@ -67,6 +95,10 @@ const UsersContainer = () => { const selectAllChecked = users && users.items.length > 0 && selected.length > 0; const onSelectAll = () => setSelected((state) => state.length > 0 ? [] : users?.items.map(({ uuid }) => uuid) || []); + const setSearchTerm = useCallback(debounce((term: string) => { + setSearch(term); + }, 200), []); + return (
@@ -88,6 +120,7 @@ const UsersContainer = () => { name={'filter'} placeholder={'Begin typing to filter...'} className={'w-56 focus:w-96'} + onChange={e => setSearchTerm(e.currentTarget.value)} />
0} duration={'duration-75'}>