|
2 | 2 |
|
3 | 3 | import { faMagnifyingGlass } from "@fortawesome/free-solid-svg-icons"; |
4 | 4 | import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; |
5 | | -import { Input } from "@heroui/react"; |
| 5 | +import { Input, Spinner } from "@heroui/react"; |
6 | 6 | import { useRouter } from "next/navigation"; |
7 | | -import { useState } from "react"; |
| 7 | +import { useState, useTransition } from "react"; |
8 | 8 |
|
9 | 9 | export function SearchButton() { |
10 | 10 | const [value, setValue] = useState(""); |
| 11 | + const [isPending, startTransition] = useTransition(); |
11 | 12 | const router = useRouter(); |
12 | 13 |
|
13 | 14 | const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => { |
14 | | - if (event.key === "Enter") { |
15 | | - router.push(`/search?q=${value}`); |
| 15 | + if (event.key === "Enter" && value.trim()) { |
| 16 | + startTransition(() => { |
| 17 | + router.push(`/search?q=${encodeURIComponent(value.trim())}`); |
| 18 | + }); |
| 19 | + } |
| 20 | + }; |
| 21 | + |
| 22 | + const handleSubmit = (event: React.FormEvent) => { |
| 23 | + event.preventDefault(); |
| 24 | + if (value.trim()) { |
| 25 | + startTransition(() => { |
| 26 | + router.push(`/search?q=${encodeURIComponent(value.trim())}`); |
| 27 | + }); |
16 | 28 | } |
17 | 29 | }; |
18 | 30 |
|
19 | 31 | return ( |
20 | | - <Input |
21 | | - type="search" |
22 | | - placeholder="Search packages" |
23 | | - aria-label="Search packages" |
24 | | - labelPlacement="outside" |
25 | | - startContent={ |
26 | | - <FontAwesomeIcon |
27 | | - className="text-default-600 dark:text-default-500" |
28 | | - icon={faMagnifyingGlass} |
29 | | - width={13} |
30 | | - /> |
31 | | - } |
32 | | - value={value} |
33 | | - onValueChange={setValue} |
34 | | - onKeyDown={handleKeyDown} |
35 | | - > |
36 | | - Search packages |
37 | | - </Input> |
| 32 | + <form onSubmit={handleSubmit}> |
| 33 | + <Input |
| 34 | + type="search" |
| 35 | + placeholder="Search packages" |
| 36 | + aria-label="Search packages" |
| 37 | + labelPlacement="outside" |
| 38 | + startContent={ |
| 39 | + isPending ? ( |
| 40 | + <Spinner size="sm" className="text-default-600" /> |
| 41 | + ) : ( |
| 42 | + <FontAwesomeIcon |
| 43 | + className="text-default-600 dark:text-default-500" |
| 44 | + icon={faMagnifyingGlass} |
| 45 | + width={13} |
| 46 | + /> |
| 47 | + ) |
| 48 | + } |
| 49 | + value={value} |
| 50 | + onValueChange={setValue} |
| 51 | + onKeyDown={handleKeyDown} |
| 52 | + isDisabled={isPending} |
| 53 | + > |
| 54 | + Search packages |
| 55 | + </Input> |
| 56 | + </form> |
38 | 57 | ); |
39 | 58 | } |
0 commit comments