/[sudobot]/trunk/docs/components/Searching/SearchModal.tsx
ViewVC logotype

Annotation of /trunk/docs/components/Searching/SearchModal.tsx

Parent Directory Parent Directory | Revision Log Revision Log


Revision 626 - (hide annotations)
Sat Sep 7 09:38:45 2024 UTC (6 months, 3 weeks ago) by rakinar2
File MIME type: application/typescript
File size: 5206 byte(s)
chore: sync with git

1 rakinar2 575 import useDebouncedState from "@/hooks/useDebouncedState";
2     import { Button, CircularProgress, TextField } from "@mui/material";
3     import { useEffect, useState } from "react";
4     import { MdClose } from "react-icons/md";
5     import SearchResult from "./SearchResult";
6    
7     type SearchModalProps = {
8     onClose: () => void;
9     };
10    
11     export type SearchResultItem = {
12     title?: string;
13     description?: string;
14     data: string;
15     match: "title" | "description" | "data";
16     url: string;
17     };
18    
19     export default function SearchModal({ onClose }: SearchModalProps) {
20 rakinar2 626 const [query, , setQuery] = useDebouncedState<string | null>(null, 500);
21 rakinar2 575 const [results, setResults] = useState<SearchResultItem[] | null>(null);
22     const [isLoading, setIsLoading] = useState(false);
23     const [isNotFound, setIsNotFound] = useState(false);
24    
25     useEffect(() => {
26     if (!query?.trim()) {
27     return;
28     }
29    
30     const controller = new AbortController();
31    
32 rakinar2 626 setIsLoading(true);
33 rakinar2 575
34     fetch(`/search?q=${encodeURIComponent(query)}`, {
35     signal: controller.signal,
36     })
37     .then(response => response.json())
38     .then(data => {
39 rakinar2 626 setIsNotFound(false);
40 rakinar2 575 setIsLoading(false);
41     setResults(data.results);
42 rakinar2 626 setIsNotFound(data.results.length === 0);
43 rakinar2 575 })
44     .catch(console.error);
45    
46     return () => controller.abort();
47     }, [query]);
48    
49     return (
50     <>
51     <div
52     className="h-[100vh] w-[100vw] fixed top-0 left-0 bg-[rgba(0,0,0,0.3)] z-[10001]"
53     onClick={onClose}
54     >
55     <div
56     onClick={event => event.stopPropagation()}
57     className="max-h-[95vh] block z-[10002] shadow-[0_0_1px_1px_rgba(255,255,255,0.2)] fixed bottom-[10px] lg:top-[50vh] left-[50%] translate-x-[-50%] lg:translate-y-[-50%] bg-[#222] min-h-[50vh] overflow-y-scroll w-[calc(100%-20px)] lg:w-[auto] md:min-w-[50vw] rounded-md p-4"
58     >
59     <div className="text-xl lg:text-2xl text-center mb-5 grid grid-cols-[1fr_5fr_1fr]">
60     <span></span>
61     <span>Search Docs</span>
62     <div className="flex justify-end">
63     <Button
64     style={{ minWidth: 0, color: "white" }}
65     onClick={onClose}
66     >
67     <MdClose />
68     </Button>
69     </div>
70     </div>
71    
72     <TextField
73     fullWidth
74     autoFocus
75     type="text"
76     variant="outlined"
77     placeholder="Type here to search"
78     onChange={event => setQuery(event.target.value.trim())}
79     onKeyUp={event => {
80     if (!(event.target as HTMLInputElement).value) {
81     setQuery(null);
82     setResults(null);
83     }
84    
85     if (isNotFound) {
86     setIsNotFound(false);
87     }
88     }}
89     />
90     <br />
91     <div className="mt-4">
92     {isLoading ? (
93     <div className="flex justify-center items-center">
94     <CircularProgress />
95     </div>
96     ) : results && results.length > 0 && !isNotFound ? (
97     <>
98     {results?.length && (
99     <>
100     <p className="text-[#aaa] text-sm">
101     Found {results.length} results.
102     </p>
103     <br />
104     </>
105     )}
106    
107     {results?.map((result, index) => (
108     <SearchResult
109     result={result}
110     query={query ?? ""}
111     key={index}
112     onClick={onClose}
113     />
114     ))}
115     </>
116     ) : isNotFound ? (
117     <h3 className="text-lg md:text-xl text-center">
118     No results found.{" "}
119     <span className="text-[#999]">
120     Maybe search again with a different
121     keyboard?
122     </span>
123     </h3>
124     ) : (
125     ""
126     )}
127     </div>
128     </div>
129     </div>
130     </>
131     );
132     }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26