Skip to content

Commit 31c2f26

Browse files
authored
feat(react-instantsearch): migrate recommend demo (#484)
1 parent a886ef8 commit 31c2f26

37 files changed

+3459
-0
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
node_modules
2+
3+
/.parcel-cache
4+
/dist
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"singleQuote": true,
3+
"proseWrap": "never",
4+
"trailingComma": "es5"
5+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# recommend
2+
3+
## Get started
4+
5+
To run this project locally, install the dependencies and run the local server:
6+
7+
```sh
8+
npm install
9+
npm start
10+
```
11+
12+
Alternatively, you may use [Yarn](https://http://yarnpkg.com/):
13+
14+
```sh
15+
yarn
16+
yarn start
17+
```
18+
19+
Open http://localhost:1234 to see your app.
1.88 KB
Loading
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
7+
<link rel="shortcut icon" href="favicon.png" type="image/x-icon" />
8+
9+
<!--
10+
Do not use @7 in production, use a complete version like x.x.x, see website for latest version:
11+
https://community.algolia.com/react-instantsearch/Getting_started.html#load-the-algolia-theme
12+
-->
13+
<link
14+
rel="stylesheet"
15+
href="https://cdn.jsdelivr.net/npm/instantsearch.css@8/themes/reset-min.css"
16+
/>
17+
18+
<title>Algolia Recommend</title>
19+
</head>
20+
21+
<body>
22+
<noscript>You need to enable JavaScript to run this app.</noscript>
23+
<div id="root"></div>
24+
25+
<script type="module" src="src/index.tsx"></script>
26+
</body>
27+
</html>
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"name": "recommend",
3+
"version": "0.1.0",
4+
"private": true,
5+
"scripts": {
6+
"start": "parcel index.html",
7+
"build": "parcel build index.html"
8+
},
9+
"dependencies": {
10+
"@algolia/autocomplete-js": "1.17.1",
11+
"@algolia/autocomplete-theme-classic": "1.17.1",
12+
"@algolia/ui-components-horizontal-slider-react": "1.2.2",
13+
"@algolia/ui-components-horizontal-slider-theme": "1.2.2",
14+
"algoliasearch": "4.23.3",
15+
"react": "18.3.1",
16+
"react-dom": "18.3.1",
17+
"react-instantsearch": "7.9.0",
18+
"react-router-dom": "^6.23.1",
19+
"search-insights": "2.14.0"
20+
},
21+
"devDependencies": {
22+
"@types/react-dom": "18.3.0",
23+
"parcel": "2.12.0",
24+
"typescript": "5.1.3"
25+
}
26+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
* {
2+
box-sizing: border-box;
3+
}
4+
5+
body {
6+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
7+
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
8+
sans-serif;
9+
-webkit-font-smoothing: antialiased;
10+
-moz-osx-font-smoothing: grayscale;
11+
padding: 0.5rem;
12+
}
13+
14+
h3 {
15+
margin-bottom: 0.5rem;
16+
margin-top: 1rem;
17+
}
18+
19+
.container {
20+
margin: 0 auto;
21+
max-width: 1100px;
22+
}
23+
24+
.product-image {
25+
min-width: 150px;
26+
min-height: 200px;
27+
background-color: var(--auc-primary-color);
28+
}
29+
30+
.title a {
31+
text-decoration: none;
32+
color: var(--auc-dark-color);
33+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
:root {
2+
--auc-primary-color: #9698c3;
3+
--auc-muted-color: #c4c4c4;
4+
--auc-dark-color: #0f0f0f;
5+
}
6+
7+
.auc-Recommend-list {
8+
display: grid;
9+
gap: 0.5rem;
10+
list-style: none;
11+
margin: 0;
12+
outline-color: var(--auc-primary-color);
13+
outline-offset: 0.5rem;
14+
padding: 0;
15+
}
16+
17+
.auc-Recommend-list {
18+
grid-template-columns: repeat(2, 1fr);
19+
}
20+
21+
@media (min-width: 999px) {
22+
.auc-Recommend-list {
23+
grid-template-columns: repeat(5, 1fr);
24+
}
25+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import {
2+
autocomplete,
3+
AutocompleteOptions,
4+
getAlgoliaResults,
5+
} from '@algolia/autocomplete-js';
6+
import React, { createElement, Fragment, useEffect, useRef } from 'react';
7+
import { render } from 'react-dom';
8+
9+
import { ProductHit } from '../../types';
10+
11+
export function Autocomplete(props: Partial<AutocompleteOptions<ProductHit>>) {
12+
const containerRef = useRef<HTMLDivElement | null>(null);
13+
14+
useEffect(() => {
15+
if (!containerRef.current) {
16+
return undefined;
17+
}
18+
19+
const search = autocomplete({
20+
container: containerRef.current,
21+
renderer: { createElement, Fragment, render: () => {} },
22+
render({ children }, root) {
23+
render(children, root);
24+
},
25+
...props,
26+
});
27+
28+
return () => {
29+
search.destroy();
30+
};
31+
// eslint-disable-next-line react-hooks/exhaustive-deps
32+
}, []);
33+
34+
return <div ref={containerRef} />;
35+
}
36+
37+
export { getAlgoliaResults };
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import React from 'react';
2+
import { InsightsClient } from 'search-insights';
3+
4+
import { indexName } from '../../config';
5+
import { ProductHit } from '../../types';
6+
7+
type BundleItemProps<TObject> = {
8+
item: TObject;
9+
onSelect(item: TObject): void;
10+
insights: InsightsClient;
11+
};
12+
13+
export const BundleItem: React.FC<BundleItemProps<ProductHit>> = ({
14+
item,
15+
onSelect,
16+
insights,
17+
}) => {
18+
return (
19+
<a
20+
className="Hit Hit-link"
21+
href={item.url}
22+
onClick={(event) => {
23+
event.preventDefault();
24+
25+
onSelect(item);
26+
insights('clickedObjectIDs', {
27+
objectIDs: [item.objectID],
28+
eventName: 'Product Clicked',
29+
index: indexName,
30+
});
31+
}}
32+
>
33+
<div className="Hit-Image">
34+
<img src={item.image_urls[0]} alt={item.name} />
35+
</div>
36+
</a>
37+
);
38+
};

0 commit comments

Comments
 (0)