Skip to content

Instantly share code, notes, and snippets.

@ljaviertovar
Last active October 3, 2022 01:15
Show Gist options
  • Save ljaviertovar/4d86389aec325607c0fbf6417e05222d to your computer and use it in GitHub Desktop.
Save ljaviertovar/4d86389aec325607c0fbf6417e05222d to your computer and use it in GitHub Desktop.
Autocomplete search component
import { Card, Col, Input, Row, Text, User } from "@nextui-org/react"
import { useEffect, useRef, useState } from "react"
import { Country } from "../../ts/interfaces/Country.interface"
import classes from "./ui.module.css"
interface Props {
data: Country[];
}
const Autocomplete = ({ data }: Props) => {
const inputSearchRef = useRef < HTMLInputElement > null
const [searchedValue, setSearchedValue] = useState("")
const [suggestions, setSuggestions] = useState < Country[]> []
const [selectedSuggestion, setSelectedSuggestion] = useState("")
const [activeSuggestion, setActiveSuggestion] = useState(0)
useEffect(() => {
if (inputSearchRef.current) {
inputSearchRef.current.focus()
}
}, [])
const handleChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
if (event.target.value !== "") {
const filteredSuggestions = data.filter((itemData) => {
const value = event.target.value.toUpperCase()
const name = itemData.name.common.toUpperCase()
return value && name.startsWith(value) && name !== value
})
setSearchedValue(event.target.value)
setSuggestions(filteredSuggestions)
}
}
const handleKeyDown = (
event: React.KeyboardEvent<HTMLInputElement>
): void => {
if (event.key === "ArrowDown" && activeSuggestion < suggestions.length) {
setActiveSuggestion(activeSuggestion + 1)
} else if (event.key === "ArrowUp" && activeSuggestion > 1) {
setActiveSuggestion(activeSuggestion - 1)
} else if (event.key === "Enter") {
setSearchedValue(suggestions[activeSuggestion - 1].name.common)
setSelectedSuggestion(suggestions[activeSuggestion - 1].name.common)
setSuggestions([])
setActiveSuggestion(0)
}
}
const handleClick = (value: string) => {
setSelectedSuggestion(value)
setSearchedValue(value)
setSuggestions([])
setActiveSuggestion(0)
//do something else
}
return (
<div className={classes.autocomplete}>
<Input
bordered
labelPlaceholder="Search your Country"
size="xl"
value={searchedValue}
onChange={handleChange}
onKeyDown={handleKeyDown}
ref={inputSearchRef}
color="secondary"
/>
<Card css={{ marginTop: "0.5rem" }}>
<Card.Body css={{ padding: "0" }}>
{!suggestions.length &&
searchedValue.length &&
!selectedSuggestion.length ? (
<Row className={classes.itemListNot}>
<Col>
<Text>Nothing to show :(</Text>
</Col>
</Row>
) : (
<>
{suggestions.map(({ name, flags }: Country, index) => (
<Row
key={index}
className={`${classes.itemList} ${
index === activeSuggestion - 1 ? classes.activeItem : ""
}`}
onClick={() => handleClick(name.common)}
>
<Col>
<User src={flags.svg} name={name.common} squared />
</Col>
</Row>
))}
</>
)}
</Card.Body>
</Card>
<Text size="$xs">Country selected: {selectedSuggestion}</Text>
</div>
)
}
export default Autocomplete
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment