diff --git a/src/App.css b/src/App.css
index b9d355d..74b17e3 100644
--- a/src/App.css
+++ b/src/App.css
@@ -2,7 +2,6 @@
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
- text-align: center;
}
.logo {
diff --git a/src/App.tsx b/src/App.tsx
index afe48ac..0492646 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,34 +1,15 @@
-import { useState } from 'react'
-import reactLogo from './assets/react.svg'
-import viteLogo from '/vite.svg'
-import './App.css'
+import './App.css';
+import Input from './components/Input';
function App() {
- const [count, setCount] = useState(0)
+ const placeholder = "Type something to search...";
+
+ const handleSelectItem = (value: any) => {
+ alert(`Search result: ${value}`);
+ };
return (
- <>
-
- Vite + React
-
-
-
- Edit src/App.tsx and save to test HMR
-
-
-
- Click on the Vite and React logos to learn more
-
- >
+
)
}
diff --git a/src/components/Input/index.tsx b/src/components/Input/index.tsx
index 453c742..6c8785a 100644
--- a/src/components/Input/index.tsx
+++ b/src/components/Input/index.tsx
@@ -1,21 +1,72 @@
import "./input.scss";
import { fetchData } from "../../utils/fetch-data";
-import { debounce } from "../../utils/deboucne";
+import { debounce } from "../../utils/debounce";
import Loader from "../Loader";
+import { useEffect, useState } from "react";
export interface InputProps {
- /** Placeholder of the input */
placeholder?: string;
- /** On click item handler */
onSelectItem: (item: string) => void;
}
const Input = ({ placeholder, onSelectItem }: InputProps) => {
// DO NOT remove this log
- console.log('input re-render')
+ // console.log('input re-render', placeholder);
// Your code start here
- return
+ const DEBOUNCE_PERIOD = 100;
+
+ const [result, setResult] = useState([]);
+ const [errMessage, setErrMessage] = useState('');
+ const [searchText, setSearchText] = useState('');
+ const [isLoading, setIsLoading] = useState(false);
+
+ useEffect(() => {
+ handleFetchingData();
+ console.log(result);
+ }, [searchText]);
+
+ const handleFetchingData = async () => {
+ setIsLoading(true);
+
+ try {
+ const response = await fetchData(searchText);
+ setSearchText(searchText);
+ setResult(response);
+ setErrMessage('');
+ } catch (error) {
+ setErrMessage(error as string);
+ setResult([]);
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ const handleChangeInput = debounce((e: any) => {
+ setSearchText(e.target.value)
+ }, DEBOUNCE_PERIOD);
+
+ return (
+
+
+ {isLoading &&
}
+ {
+ result
+ ? searchText &&
+ {result.map((item, index) => (
+ - onSelectItem(item)}>{item}
+ ))}
+
+ :
No results
+
+ }
+ {errMessage &&
{errMessage}
}
+
+ )
// Your code end here
};
diff --git a/src/components/Input/input.scss b/src/components/Input/input.scss
index 1dafbe7..e8920e0 100644
--- a/src/components/Input/input.scss
+++ b/src/components/Input/input.scss
@@ -1,6 +1,45 @@
* {
box-sizing: border-box;
-}
-html{
font-size: 16px;
}
+
+.search {
+ &__panel {
+ max-width: 456px;
+ margin: 60px auto;
+ }
+
+ &__box {
+ width: 100%;
+ padding: 12px 20px;
+ }
+
+ &__results {
+ margin: 0;
+ padding: 0;
+ list-style-type: none;
+ max-height: 480px;
+ overflow: auto;
+ }
+
+ &__item {
+ padding: 12px 20px;
+ background-color: #fafafa;
+ cursor: pointer;
+ transition: all .3s;
+
+ &:hover {
+ background-color: #efefef;
+ }
+ }
+
+ &__message, &__error {
+ padding: 12px 20px;
+ background-color: #fafafa;
+ }
+
+ &__error {
+ color: rgba(255, 0, 0, 1);
+ background: rgba(255, 0, 0, 0.1);
+ }
+}
diff --git a/src/index.css b/src/index.css
index 6119ad9..52810fd 100644
--- a/src/index.css
+++ b/src/index.css
@@ -24,10 +24,6 @@ a:hover {
body {
margin: 0;
- display: flex;
- place-items: center;
- min-width: 320px;
- min-height: 100vh;
}
h1 {
diff --git a/src/utils/deboucne.ts b/src/utils/debounce.ts
similarity index 100%
rename from src/utils/deboucne.ts
rename to src/utils/debounce.ts