From c0f0bbf1e220d354fee819696c69ab63bf203435 Mon Sep 17 00:00:00 2001 From: NaGyeong Park Date: Wed, 7 Dec 2022 19:55:04 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20SearchBar=20component=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20resolve=20#186?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/components/todos/SearchBar.tsx | 125 ++++++++++++++++++++++ client/src/container/todos/TableModal.tsx | 2 +- client/src/images/Search.svg | 4 + 3 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 client/src/components/todos/SearchBar.tsx create mode 100644 client/src/images/Search.svg diff --git a/client/src/components/todos/SearchBar.tsx b/client/src/components/todos/SearchBar.tsx new file mode 100644 index 0000000..4ac66e6 --- /dev/null +++ b/client/src/components/todos/SearchBar.tsx @@ -0,0 +1,125 @@ +import { ReactElement, useState } from 'react'; +import { useAtomValue } from 'jotai'; +import { toast } from 'react-toastify'; + +import { PlainTodo } from '@todo/todo.type'; +import { todoList } from '@util/GlobalState'; +import Search from '@images/Search.svg'; + +import Text from '@components/Text'; +import Image from '@components/Image'; +import styled from 'styled-components'; +import { PRIMARY_COLORS } from '@util/Constants'; + +const Wrapper = styled.div` + position: relative; + width: 100%; +`; + +const Ul = styled.ul` + list-style: none; + padding-left: 0px; + margin: 8px 0; +`; + +const UlWrapper = styled.div` + position: absolute; + width: 100%; + margin: 10px 0; + background-color: white; + border: 1px solid #e2e2e2; + border-radius: 5px; + li:hover { + cursor: pointer; + background-color: ${PRIMARY_COLORS.lightGray}; + } +`; + +const ListWrapper = styled.div` + width: 100%; + display: flex; + align-items: center; + margin: 5px 0; + + img { + margin: 0 5px; + } + p { + padding: 5px; + } +`; + +const InputWrapper = styled(ListWrapper)` + display: flex; + justify-content: center; + background: white; + border: 1px solid ${PRIMARY_COLORS.lightGray}; + border-radius: 5px; + padding: 3px 0; +`; + +const SearchBar = ({ onClick }: { onClick: Function }): ReactElement => { + const todoListAtom = useAtomValue(todoList); + const [searchTodoList, setSearchTodoList] = useState([]); + const [inputValue, setInputValue] = useState(''); + + const inputEventPromiseWrapper = (event: React.ChangeEvent): void => { + onInput(event) + .then(() => {}) + .catch(() => {}); + }; + + const onInput = async (event: React.ChangeEvent): Promise => { + setInputValue(event.target.value); + if (event.target.value.length > 1) { + return await todoListAtom + .getTodoBySearchKeyword(event.target.value, 10) + .then((data: PlainTodo[]) => { + setSearchTodoList((prev) => [...data]); + }) + .catch((err) => { + toast.error(err); + }); + } + }; + + const listOnClick = (selectTodo: PlainTodo): void => { + setInputValue(''); + setSearchTodoList([]); + onClick(selectTodo); + }; + + return ( + + + + + + {searchTodoList.length > 0 && ( + +
    + {searchTodoList.map((todo: PlainTodo) => { + return ( +
  • + listOnClick(todo)}> + + + +
  • + ); + })} +
+
+ )} +
+ ); +}; + +export default SearchBar; diff --git a/client/src/container/todos/TableModal.tsx b/client/src/container/todos/TableModal.tsx index 4eb553e..8b1d5ad 100644 --- a/client/src/container/todos/TableModal.tsx +++ b/client/src/container/todos/TableModal.tsx @@ -73,7 +73,7 @@ const Container = styled.div` position: relative; width: 100%; color: ${darkGray}; - front-family: 'SanSerif' + font-family: 'SanSerif'; font-size: 15px; padding: 5px; border: 1px solid ${lightGray}; diff --git a/client/src/images/Search.svg b/client/src/images/Search.svg new file mode 100644 index 0000000..599ea04 --- /dev/null +++ b/client/src/images/Search.svg @@ -0,0 +1,4 @@ + + + +