From 203e61e255879bf61c775ba6ad26521d88f80be7 Mon Sep 17 00:00:00 2001 From: Park Na Yeon Date: Wed, 2 Nov 2022 13:56:34 +0900 Subject: [PATCH] [FEAT] Add atom componts about post create form --- client/src/asset/icons/icon-del.svg | 3 + .../components/postCreate/atoms/TagInput.tsx | 120 ++++++++++++++++++ .../components/postCreate/atoms/TargetAge.tsx | 39 ++++++ .../src/components/postCreate/atoms/Title.tsx | 36 ++++++ .../postCreate/molecules/CreateForm.tsx | 33 +++++ .../postInventory/molecules/InventoryList.tsx | 18 --- client/src/pages/PostCreatePage.tsx | 58 +++++++++ client/src/routes/AppRoute.tsx | 4 +- 8 files changed, 292 insertions(+), 19 deletions(-) create mode 100644 client/src/asset/icons/icon-del.svg create mode 100644 client/src/components/postCreate/atoms/TagInput.tsx create mode 100644 client/src/components/postCreate/atoms/TargetAge.tsx create mode 100644 client/src/components/postCreate/atoms/Title.tsx create mode 100644 client/src/components/postCreate/molecules/CreateForm.tsx create mode 100644 client/src/pages/PostCreatePage.tsx diff --git a/client/src/asset/icons/icon-del.svg b/client/src/asset/icons/icon-del.svg new file mode 100644 index 0000000..947ebbd --- /dev/null +++ b/client/src/asset/icons/icon-del.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/src/components/postCreate/atoms/TagInput.tsx b/client/src/components/postCreate/atoms/TagInput.tsx new file mode 100644 index 0000000..d7fb112 --- /dev/null +++ b/client/src/components/postCreate/atoms/TagInput.tsx @@ -0,0 +1,120 @@ +import { useState } from 'react'; +// import { UseFormRegister } from 'react-hook-form'; +import styled from 'styled-components'; +import { theme } from '../../../styles/theme'; +import DelBtn from '../../../asset/icons/icon-del.svg'; + +// interface TagInputProps { +// setValue: UseFormRegister; +// clearErrors: UseFormRegister; +// } + +function TagInput() { + const [text, setText] = useState(''); + const tagArray: Array = []; // watch('tagArray'); + + // const handleKeyUp = (e: KeyboardEvent) => { + // const reg = /[^\wㄱ-힣]/g; + + // if (reg.exec(e.target?.value)) { + // setText(e.target?.value.replace(reg, '')); + // } + + // if (e.keyCode === 188 || (e.keyCode === 32 && e.target.value !== '')) { + // const tagText = e.target.value.replace(reg, ''); + // if (tagText.length === 0) { + // setText(''); + // } else if (!tagArray.includes(tagText)) { + // setValue('tagArray', [...tagArray, tagText]); + // setText(''); + // clearErrors('tagArray'); + // } else { + // setText(''); + // } + // } + // }; + + return ( + + + {tagArray && + tagArray.map((el) => ( + + {el} + + + ))} + + + + ); +} + +export default TagInput; + +const HashContainer = styled.div<{ error: boolean }>` + height: auto; + margin-top: 30px; + padding: 5px; + color: rgb(52, 58, 64); + font-size: 1.125rem; + display: flex; + flex-wrap: wrap; + letter-spacing: -0.6px; + color: #444241; + border: 2px solid ${({ theme, error }) => (error ? theme.color.lightGray : theme.color.yellow)}; + @media screen and (max-width: 1200px) { + display: block; + } +`; + +const HashWrapBox = styled.div` + display: flex; + flex-wrap: wrap; +`; + +const HashItem = styled.div` + margin-right: 5px; + margin-bottom: 5px; + padding: 5px; + border-radius: 56px; + display: flex; + align-items: center; + justify-content: center; + width: auto; + background: ${theme.color.yellow}; + color: ${theme.color.navy}; + font-weight: bold; + font-size: 15px; + cursor: pointer; +`; + +const HashInput = styled.input` + display: block; + outline: none; + cursor: text; + margin: 5px; + border: none; + min-width: 300px; + width: 90%; +`; + +const HashDelBtn = styled.button` + width: 8px; + height: 8px; + background: url(${DelBtn}); + background-position: center; + background-size: contain; + background-repeat: no-repeat; +`; diff --git a/client/src/components/postCreate/atoms/TargetAge.tsx b/client/src/components/postCreate/atoms/TargetAge.tsx new file mode 100644 index 0000000..18ecfd1 --- /dev/null +++ b/client/src/components/postCreate/atoms/TargetAge.tsx @@ -0,0 +1,39 @@ +import { UseFormRegister } from 'react-hook-form'; +import styled from 'styled-components'; + +type TargetAgeProps = { + register: UseFormRegister; +}; + +function TargetAge({ register }: TargetAgeProps) { + return ( + + + + + + + + + + + ); +} +export default TargetAge; + +const TargetWrap = styled.div` + margin-top: 30px; +`; + +const TargetAgeSelect = styled.select<{ error: boolean }>` + width: 250px; + height: 40px; + border: 2px solid ${({ error, theme }) => (error ? theme.color.lightGray : theme.color.yellow)}; + border-radius: 3px; + @media screen and (max-width: 550px) { + width: 100%; + & > option { + width: 100%; + } + } +`; diff --git a/client/src/components/postCreate/atoms/Title.tsx b/client/src/components/postCreate/atoms/Title.tsx new file mode 100644 index 0000000..0d7cfc7 --- /dev/null +++ b/client/src/components/postCreate/atoms/Title.tsx @@ -0,0 +1,36 @@ +import { UseFormRegister } from 'react-hook-form'; +import styled from 'styled-components'; + +type TitleProps = { + register: UseFormRegister; +}; + +function Title({ register }: TitleProps) { + return ( + + + + ); +} +export default Title; + +const TitleWrap = styled.div` + margin-top: 30px; +`; + +const TitleInput = styled.input<{ error: boolean }>` + height: 40px; + border: 2px solid ${({ theme, error }) => (error ? theme.color.lightGray : theme.color.yellow)}; + border-radius: 3px; + @media screen and (max-width: 612px) { + width: 100%; + } + @media (min-width: 612px) { + width: 413px; + } +`; diff --git a/client/src/components/postCreate/molecules/CreateForm.tsx b/client/src/components/postCreate/molecules/CreateForm.tsx new file mode 100644 index 0000000..760296c --- /dev/null +++ b/client/src/components/postCreate/molecules/CreateForm.tsx @@ -0,0 +1,33 @@ +import { useEffect } from 'react'; +import { useForm } from 'react-hook-form'; +import Title from '../atoms/Title'; +import TargetAge from '../atoms/TargetAge'; +import TagInput from '../atoms/TagInput'; + +function CreateForm() { + const { register, setValue } = useForm({ + mode: 'onBlur', + defaultValues: { + tagArray: [], + title: '', + para: { para: '', img: [] }, + age: '', + }, + }); + + useEffect(() => { + setValue('title', ''); + setValue('para', { para: '', img: [] }); + setValue('age', ''); + setValue('tagArray', []); + }, [setValue]); + + return ( +
+ + <TargetAge register={register} /> + <TagInput /> + </form> + ); +} +export default CreateForm; diff --git a/client/src/components/postInventory/molecules/InventoryList.tsx b/client/src/components/postInventory/molecules/InventoryList.tsx index a3cda72..976f178 100644 --- a/client/src/components/postInventory/molecules/InventoryList.tsx +++ b/client/src/components/postInventory/molecules/InventoryList.tsx @@ -6,23 +6,6 @@ import useObserve from '../../../hooks/useObserve'; import { getPostListRead } from '../../../networks/post/http'; import { useAppSelector } from '../../../redux/hooks'; import InventoryItem from '../atoms/InventoryItem'; -import DropdownBox from '../../common/molecules/DropdownBox'; - -// interface SearchData { -// option: string; -// inputs: string; -// } - -// interface InventoryProps { -// postFilter: string; -// searchData: SearchData; -// } - -// interface QueryKey { -// age: string | undefined; -// postFilter: string; -// searchData: SearchData; -// } interface LoadedPostProps { queryKey: any; @@ -59,7 +42,6 @@ function InventoryList() { return ( <PostListBodyContainer> - <DropdownBox /> <PostListBodyLayout> {postData && ( <> diff --git a/client/src/pages/PostCreatePage.tsx b/client/src/pages/PostCreatePage.tsx new file mode 100644 index 0000000..99cb5f2 --- /dev/null +++ b/client/src/pages/PostCreatePage.tsx @@ -0,0 +1,58 @@ +import styled from 'styled-components'; +import { useLocation } from 'react-router-dom'; +import CreateForm from '../components/postCreate/molecules/CreateForm'; + +function PostCreatePage() { + const { pathname } = useLocation(); + const pathArr = pathname.split('/'); + const pathValue = pathArr[2]; + return ( + <PostCreateMain> + <PostCreateContainer> + <PostHeader>{pathValue === 'create' ? '질문하기' : ' 질문 수정 하기'}</PostHeader> + <CreateForm /> + </PostCreateContainer> + </PostCreateMain> + ); +} + +export default PostCreatePage; + +const PostCreateMain = styled.main``; + +const PostCreateContainer = styled.div` + display: flex; + flex-direction: column; + margin: 100px auto 0; + padding: 70px 0; + @media screen and (max-width: 550px) { + width: 333px; + padding: 50px 0; + } + @media (min-width: 550px) and (max-width: 612px) { + width: 500px; + } + @media (min-width: 612px) and (max-width: 768px) { + width: 500px; + } + @media (min-width: 768px) and (max-width: 992px) { + width: 500px; + } + @media (min-width: 992px) and (max-width: 1200px) { + width: 697px; + } + @media (min-width: 1200px) { + width: 865px; + } +`; + +const PostHeader = styled.h2` + position: relative; + font-size: 30px; + width: 100%; + margin: 0 auto 10px; + @media screen and (max-width: 612px) { + font-size: 25px; + text-align: center; + } +`; diff --git a/client/src/routes/AppRoute.tsx b/client/src/routes/AppRoute.tsx index 598a499..66b3d6a 100644 --- a/client/src/routes/AppRoute.tsx +++ b/client/src/routes/AppRoute.tsx @@ -1,12 +1,14 @@ import { Routes, Route } from 'react-router-dom'; import PostInventoryPage from '../pages/PostInventoryPage'; +import PostCreatePage from '../pages/PostCreatePage'; function AppRoute() { return ( <Routes> <Route path="/intro" element={<div>test</div>} /> <Route path="/generation/:age" element={<PostInventoryPage />} /> - <Route path='/my' element={<div>my</div>} /> + <Route path="/post/create" element={<PostCreatePage />} /> + <Route path="/my" element={<div>my</div>} /> </Routes> ); }