Skip to content

Commit a7566ed

Browse files
authored
Merge pull request CodingCatDev#224 from CodingCatDev/main
add algolia searchmodale to dev
2 parents 2a56e1c + 2fe6f00 commit a7566ed

3 files changed

Lines changed: 55 additions & 25 deletions

File tree

frontend/main/src/components/algolia/SearchModal.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
import React, { useCallback, useEffect, useState } from 'react';
1+
import useOnClickOutside from '@/hooks/useOnClickOutside';
2+
import React, { useCallback, useEffect, useRef, useState } from 'react';
23
import AlgoliaInstantSearch from './algoliaInstantSearch';
34

45
export default function SearchModal(): JSX.Element {
56
const [show, setShow] = useState(false);
7+
const ref = useRef(null);
8+
useOnClickOutside(ref, () => setShow(false));
69

710
const showModal = () => {
811
setShow(true);
@@ -51,7 +54,10 @@ export default function SearchModal(): JSX.Element {
5154
'scale-in-center 0.3s cubic-bezier(0.250, 0.460, 0.450, 0.940) both',
5255
}}
5356
>
54-
<section className="absolute grid w-full h-full gap-4 p-4 grid-rows-search">
57+
<section
58+
className="absolute grid w-full h-full gap-4 p-4 grid-rows-search"
59+
ref={ref}
60+
>
5561
<AlgoliaInstantSearch show={show}></AlgoliaInstantSearch>
5662
<button
5763
className="absolute top-0 right-0 p-5 text-2xl transition-colors rounded-full text-primary-900 hover:text-secondary-500 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-primary-900"

frontend/main/src/components/algolia/algoliaInstantSearch.tsx

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState, useEffect, createRef } from 'react';
1+
import React, { useState } from 'react';
22

33
import algoliasearch from 'algoliasearch/lite';
44
import {
@@ -7,28 +7,11 @@ import {
77
Index,
88
connectStateResults,
99
PoweredBy,
10+
MenuSelect,
1011
} from 'react-instantsearch-dom';
1112
import CustomSearchBox from './customSearchBox';
1213
import * as hitComps from './customHitComponents';
1314

14-
const useClickOutside = (
15-
ref: { current: { contains: (arg0: any) => any } },
16-
handler: () => any,
17-
events: string[]
18-
) => {
19-
if (!events) events = [`mousedown`, `touchstart`];
20-
const detectClickOutside = (event: { target: any }) =>
21-
!ref.current.contains(event.target) && handler();
22-
useEffect(() => {
23-
for (const event of events)
24-
document.addEventListener(event, detectClickOutside);
25-
return () => {
26-
for (const event of events)
27-
document.removeEventListener(event, detectClickOutside);
28-
};
29-
});
30-
};
31-
3215
const algoliaClient = algoliasearch(
3316
process.env.NEXT_PUBLIC_ALGOLIA_APP_ID || '',
3417
process.env.NEXT_PUBLIC_ALGOLIA_SEARCH_API_KEY || ''
@@ -56,9 +39,8 @@ const Stats = connectStateResults(({ searchResults: res }: any) => {
5639
);
5740
});
5841

59-
const HitList = (show: any) => {
60-
const [query, setQuery] = useState(``);
61-
const [focus, setFocus] = useState(false);
42+
const HitList = ({ show }: { show: boolean }): JSX.Element => {
43+
const [, setFocus] = useState(false);
6244

6345
const searchClient = {
6446
search(requests: any) {
@@ -99,8 +81,9 @@ const HitList = (show: any) => {
9981
))}
10082
<footer>
10183
<hr className="mb-2 opacity-20 text-primary-900" />
102-
<div className="justify-self-end">
84+
<div className="flex justify-between">
10385
<PoweredBy />
86+
<MenuSelect attribute="type" />
10487
</div>
10588
</footer>
10689
</InstantSearch>
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { RefObject, useEffect } from 'react';
2+
const MOUSEDOWN = 'mousedown';
3+
const TOUCHSTART = 'touchstart';
4+
5+
type HandledEvents = [typeof MOUSEDOWN, typeof TOUCHSTART];
6+
type HandledEventsType = HandledEvents[number];
7+
type PossibleEvent = {
8+
[Type in HandledEventsType]: HTMLElementEventMap[Type];
9+
}[HandledEventsType];
10+
type Handler = (event: PossibleEvent) => void;
11+
12+
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
13+
export default function useOnClickOutside(
14+
ref: RefObject<HTMLElement>,
15+
handler: Handler
16+
) {
17+
useEffect(
18+
() => {
19+
const listener = (event: PossibleEvent) => {
20+
// Do nothing if clicking ref's element or descendent elements
21+
if (!ref.current || ref.current.contains(event.target as Node)) {
22+
return;
23+
}
24+
handler(event);
25+
};
26+
document.addEventListener('mousedown', listener);
27+
document.addEventListener('touchstart', listener);
28+
return () => {
29+
document.removeEventListener('mousedown', listener);
30+
document.removeEventListener('touchstart', listener);
31+
};
32+
},
33+
// Add ref and handler to effect dependencies
34+
// It's worth noting that because passed in handler is a new ...
35+
// ... function on every render that will cause this effect ...
36+
// ... callback/cleanup to run every render. It's not a big deal ...
37+
// ... but to optimize you can wrap handler in useCallback before ...
38+
// ... passing it into this hook.
39+
[ref, handler]
40+
);
41+
}

0 commit comments

Comments
 (0)