-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add articles search API * Add main search input
- Loading branch information
1 parent
6472fa8
commit c9b606e
Showing
27 changed files
with
543 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"presets": ["next/babel"], | ||
"plugins": [["styled-components", { "ssr": true }]] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
#!/bin/sh | ||
. "$(dirname "$0")/_/husky.sh" | ||
|
||
yarn cache:update |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
[{"locale":"en","category":"getting-started","slug":"welcome-aboard","tags":"getting started, intro, presentation","title":"Welcome aboard 👋","description":"We want to help you provide great customer support to all of your customers in a sane and sustainable way."},{"locale":"pt-BR","category":"primeiros-passos","slug":"seja-bem-vindo","tags":"primeiros passos, introdução, apresentação","title":"Seja bem-vindo 👋","description":"Queremos ajudá-lo a fornecer um ótimo suporte para todos os seus clientes de uma forma simples e sustentável."}] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
import { useRouter } from 'next/router'; | ||
import React, { useRef, useState } from 'react'; | ||
import { useEffect } from 'react'; | ||
import { RiLoader5Line, RiSearchLine } from 'react-icons/ri'; | ||
import { useQuery } from 'react-query'; | ||
import styled from 'styled-components'; | ||
|
||
import { SearchResultType } from '../../../utils/datasource'; | ||
import { searchForArticles } from '../../../utils/libs/api'; | ||
import SearchResults from './SearchResults'; | ||
|
||
export default function SearchInput() { | ||
const [isSearching, setIsSearching] = useState(false); | ||
const [cursor, setCursor] = useState(0); | ||
const [term, setTerm] = useState(''); | ||
|
||
const inputRef = useRef<HTMLInputElement>(); | ||
const router = useRouter(); | ||
|
||
const { isLoading, data } = useQuery<SearchResultType[]>(['searchResults', term], () => | ||
searchForArticles(term, router.locale) | ||
); | ||
|
||
const results = data || []; | ||
|
||
useEffect(() => { | ||
if (!isSearching) { | ||
inputRef.current.blur(); | ||
} | ||
}, [isSearching, inputRef]); | ||
|
||
useEffect(() => { | ||
if (cursor > results.length) { | ||
setCursor(0); | ||
} | ||
}, [results]); | ||
|
||
function handleKeyUp({ key }: React.KeyboardEvent<HTMLInputElement>) { | ||
if (key === 'Escape') { | ||
setIsSearching(false); | ||
return; | ||
} | ||
|
||
if (key === 'ArrowDown' && cursor < results.length) { | ||
setCursor(cursor + 1); | ||
return; | ||
} | ||
|
||
if (cursor > 0) { | ||
switch (key) { | ||
case 'ArrowUp': | ||
setCursor(cursor - 1); | ||
break; | ||
case 'Enter': | ||
handleSelect(results[cursor - 1]); | ||
} | ||
} | ||
} | ||
|
||
function handleSelect({ item }: SearchResultType) { | ||
const path = `/${item.category}/${item.slug}`; | ||
const locale = item.locale; | ||
|
||
setIsSearching(false); | ||
|
||
router.push(path, path, { locale }); | ||
} | ||
|
||
return ( | ||
<Container> | ||
<InputContainer> | ||
<Input | ||
ref={inputRef} | ||
onChange={({ target }) => setTerm(target.value)} | ||
onFocus={() => setIsSearching(true)} | ||
onKeyUp={handleKeyUp} | ||
/> | ||
|
||
<InputIconContainer>{isLoading ? <LoaderIcon /> : <SearchIcon />}</InputIconContainer> | ||
</InputContainer> | ||
|
||
{isSearching && <SearchResults cursor={cursor} results={results} onSelect={handleSelect} />} | ||
</Container> | ||
); | ||
} | ||
|
||
const Container = styled.div.attrs({ className: 'relative' })``; | ||
|
||
const InputContainer = styled.div.attrs({ | ||
className: 'transition relative text-gray-400 focus-within:text-primary-500', | ||
})``; | ||
|
||
const InputIconContainer = styled.div.attrs({ | ||
className: 'flex absolute items-center inset-y-0 right-4', | ||
})``; | ||
|
||
const Input = styled.input.attrs({ | ||
placeholder: 'Search', | ||
className: 'form-input focusable', | ||
})``; | ||
|
||
const LoaderIcon = styled(RiLoader5Line).attrs({ size: 24, className: 'animate-spin' })``; | ||
const SearchIcon = styled(RiSearchLine).attrs({ size: 24, className: '' })``; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import useTranslation from 'next-translate/useTranslation'; | ||
import React from 'react'; | ||
import styled from 'styled-components'; | ||
|
||
import { SearchResultType } from '../../../utils/datasource'; | ||
|
||
export interface SelectableItem { | ||
onSelect?: (param: SearchResultType) => void; | ||
} | ||
|
||
interface Props extends SelectableItem { | ||
cursor: number; | ||
results: SearchResultType[]; | ||
} | ||
|
||
interface ItemProps extends SelectableItem { | ||
item: SearchResultType['item']; | ||
isActive?: boolean; | ||
} | ||
|
||
export default function SearchResults({ cursor, results, onSelect }: Props) { | ||
return ( | ||
<> | ||
{results?.length > 0 && ( | ||
<ItemsList> | ||
{results.map(({ item }, index) => ( | ||
<SearchResultsItem key={item.slug} item={item} onSelect={onSelect} isActive={cursor === index + 1} /> | ||
))} | ||
</ItemsList> | ||
)} | ||
</> | ||
); | ||
} | ||
|
||
function SearchResultsItem({ item, isActive, onSelect }: ItemProps) { | ||
const { t } = useTranslation('categories'); | ||
|
||
function handleSelect() { | ||
onSelect?.({ item }); | ||
} | ||
|
||
return ( | ||
<Item className={isActive ? 'search-result-item active' : 'search-result-item'}> | ||
<ItemButton onClick={handleSelect}> | ||
<ItemCategory>{t(`${item.category}.title`)}</ItemCategory> | ||
<ItemLabel>{item.title}</ItemLabel> | ||
</ItemButton> | ||
</Item> | ||
); | ||
} | ||
|
||
const ItemsList = styled.ul.attrs({ className: 'search-result-list' })``; | ||
|
||
const Item = styled.li``; | ||
const ItemButton = styled.button``; | ||
|
||
const ItemCategory = styled.span.attrs({ className: 'search-result-description' })``; | ||
const ItemLabel = styled.span.attrs({ className: 'search-result-title' })``; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { NextApiRequest, NextApiResponse } from 'next'; | ||
|
||
import Search from '../../utils/libs/search'; | ||
|
||
export default (req: NextApiRequest, res: NextApiResponse) => { | ||
const term = req.query.term as string; | ||
const locale = req.query.locale as string; | ||
|
||
try { | ||
res.json(Search.find(term, locale)); | ||
} catch { | ||
res.json([]); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
.btn { | ||
@apply font-medium rounded-xl transition ring-inset px-4 py-2 focus:outline-none focus:ring-2; | ||
} | ||
|
||
.btn-default { | ||
@apply bg-gray-100 ring-gray-300 hover:bg-gray-200; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
.focusable { | ||
@apply ring-primary-500 ring-inset focus:bg-white focus:ring-1 focus:outline-none; | ||
} | ||
|
||
.form-input { | ||
@apply transition text-gray-800 border border-gray-200 rounded-lg py-3 pl-4 pr-10 w-full focus:border-primary-500; | ||
} |
Oops, something went wrong.