diff --git a/src/App.tsx b/src/App.tsx
index afe48ac..31ac718 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,35 +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/index.tsx";
function App() {
- const [count, setCount] = useState(0)
-
- return (
- <>
-
- Vite + React
-
-
-
- Edit src/App.tsx and save to test HMR
-
-
-
- Click on the Vite and React logos to learn more
-
- >
- )
+ const handleSelectItem = (item: string) => {
+ console.log(`Selected item: ${item}`);
+ };
+ return (
+ <>
+
+ >
+ );
}
-export default App
+export default App;
diff --git a/src/components/Input/index.tsx b/src/components/Input/index.tsx
index 453c742..10b20b9 100644
--- a/src/components/Input/index.tsx
+++ b/src/components/Input/index.tsx
@@ -1,7 +1,6 @@
import "./input.scss";
-import { fetchData } from "../../utils/fetch-data";
-import { debounce } from "../../utils/deboucne";
import Loader from "../Loader";
+import { useInput } from "./useInput";
export interface InputProps {
/** Placeholder of the input */
@@ -12,12 +11,46 @@ export interface InputProps {
const Input = ({ placeholder, onSelectItem }: InputProps) => {
// DO NOT remove this log
- console.log('input re-render')
+ console.log('input re-render');
- // Your code start here
- return
- // Your code end here
-};
+ const { loading, error, result, onChange } = useInput();
+
+ const renderResults = () => {
+ if (!Array.isArray(result)) return null;
+
+ if (result.length > 0) {
+ return (
+
+ {result.map(item => (
+ - onSelectItem(item)}
+ >
+ {item}
+
+ ))}
+
+ );
+ }
+ return No results
;
+ };
-export default Input;
+ const renderContent = () => {
+ if (loading) return ;
+ if (error) return {error}
;
+ return renderResults();
+ };
+
+ return (
+
+
+ {renderContent()}
+
+ );
+};
+export default Input;
\ No newline at end of file
diff --git a/src/components/Input/input.scss b/src/components/Input/input.scss
index 1dafbe7..1f8a803 100644
--- a/src/components/Input/input.scss
+++ b/src/components/Input/input.scss
@@ -1,6 +1,76 @@
* {
box-sizing: border-box;
}
-html{
+
+html {
font-size: 16px;
}
+
+.main {
+ width: 100%;
+ max-width: 600px;
+ margin: 0 auto;
+ padding: 20px;
+ border: 1px solid #e0e0e0;
+ border-radius: 8px;
+ background-color: #f9f9f9;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+}
+
+input {
+ padding: 10px 15px;
+ border: 2px solid #007BFF;
+ border-radius: 5px;
+ background-color: #ffffff;
+ color: #333;
+ width: 100%;
+ height: 45px;
+ transition: border-color 0.3s;
+
+ &:focus {
+ border-color: #0056b3;
+ outline: none;
+ }
+}
+
+.error {
+ color: #dc3545;
+ padding: 10px;
+ border: 1px solid currentColor;
+ background-color: rgba(220, 53, 69, 0.1);
+ border-radius: 5px;
+}
+
+.list {
+ display: flex;
+ flex-direction: column;
+ padding: 0;
+ list-style: none;
+ margin-top: 10px;
+}
+
+.item {
+ padding: 12px 15px;
+ border: 1px solid transparent;
+ background-color: #ffffff;
+ color: #333;
+ cursor: pointer;
+ transition: background-color 0.2s, border-color 0.2s;
+
+ &:hover {
+ background-color: #f1f1f1;
+ border-color: #007BFF;
+ }
+
+ &:last-child {
+ border-bottom: none;
+ }
+}
+
+.no-results {
+ color: #6c757d;
+ text-align: center;
+ padding: 10px;
+ background-color: #f9f9f9;
+ border-radius: 5px;
+}
\ No newline at end of file
diff --git a/src/components/Input/useInput.tsx b/src/components/Input/useInput.tsx
new file mode 100644
index 0000000..784d496
--- /dev/null
+++ b/src/components/Input/useInput.tsx
@@ -0,0 +1,40 @@
+import { ChangeEvent, useCallback, useRef, useState } from "react";
+import { debounce } from "../../utils/deboucne";
+import { fetchData } from "../../utils/fetch-data";
+export const useInput = () => {
+ const [ loading, setLoading ] = useState(false);
+ const [ error, setError ] = useState();
+ const [ result, setResult ] = useState();
+ const lastPromise = useRef>();
+
+ const ignoreRequest = (promise: Promise) => {
+ return lastPromise.current !== promise;
+ }
+ const handleResponse = useCallback((promise: Promise, callback: () => void) => {
+ if(ignoreRequest(promise)) return;
+ callback();
+ setLoading(false);
+ lastPromise.current = undefined;
+ }, [lastPromise]);
+ const onChange = useCallback(debounce(async (e: ChangeEvent) => {
+ const value = (e.target as HTMLInputElement).value;
+ setLoading(true);
+ setError("");
+ setResult([]);
+ let promise = fetchData(value);
+ lastPromise.current = promise;
+ promise
+ .then(data => {
+ handleResponse(promise, () => setResult(data));
+ })
+ .catch(err => {
+ handleResponse(promise, () => setError((err as string)));
+ })
+ }, 100),
+ []
+ );
+ return {
+ loading, error, result,
+ onChange
+ }
+}
\ No newline at end of file