Merge branch 'feat/components-header' into 'develop'
Feat/components header See merge request !5
Showing
6 changed files
with
335 additions
and
13 deletions
frontend/src/components/Header.js
0 → 100644
1 | +import React, { useState } from 'react'; | ||
2 | +import { NavLink, useHistory } from 'react-router-dom'; | ||
3 | +import styled from 'styled-components'; | ||
4 | +import InputBlock from './common/Input'; | ||
5 | +import SearchBox from './common/SearchBox'; | ||
6 | +import DropDownButton from './common/DropdownButton'; | ||
7 | +import Button from './common/Button'; | ||
8 | +import Modal from './SearchOptionModal'; | ||
9 | +// 헤더 사이즈 | ||
10 | +const HeaderHeight = '170px'; | ||
11 | + | ||
12 | +const HeaderTop = styled.div` | ||
13 | + background-color: black; | ||
14 | + float: up; | ||
15 | + height: 20px; | ||
16 | +`; | ||
17 | +const MainContainer = styled.div` | ||
18 | + height: ${HeaderHeight}; | ||
19 | + position: fixed; | ||
20 | + top: 0; | ||
21 | + width: 100%; | ||
22 | + z-index: 999; | ||
23 | + background-color: #ffffff; | ||
24 | + border-bottom: 1px solid #868e96; | ||
25 | +`; | ||
26 | +const MenuContainer = styled.div` | ||
27 | + position: fixed; | ||
28 | + top: 100px; | ||
29 | + left: 0px; | ||
30 | +`; | ||
31 | + | ||
32 | +const LogoContainer = styled.div` | ||
33 | + margin-top: 20px; | ||
34 | + float: left; | ||
35 | + padding: 20px; | ||
36 | + img { | ||
37 | + width: 100px; | ||
38 | + | ||
39 | + vertical-align: bottom; | ||
40 | + } | ||
41 | +`; | ||
42 | + | ||
43 | +const SearchContainer = styled.div` | ||
44 | + margin-top: 20px; | ||
45 | +`; | ||
46 | + | ||
47 | +const SLink = styled(NavLink)` | ||
48 | + list-style-type: none; | ||
49 | + color: black; | ||
50 | + float: left; | ||
51 | + line-height: 55px; | ||
52 | + vertical-align: middle; | ||
53 | + text-align: center; | ||
54 | + padding-left: 2em; | ||
55 | + padding-right: 2em; | ||
56 | + text-decoration: none !important; | ||
57 | + &:hover { | ||
58 | + background-color: #feebb6; | ||
59 | + } | ||
60 | + &.active { | ||
61 | + font-weight: 600; | ||
62 | + background-color: #feebb6; | ||
63 | + float: left; | ||
64 | + line-height: 55px; | ||
65 | + vertical-align: middle; | ||
66 | + text-align: center; | ||
67 | + padding-left: 2em; | ||
68 | + padding-right: 2em; | ||
69 | + color: black; | ||
70 | + text-decoration: none !important; | ||
71 | + } | ||
72 | +`; | ||
73 | + | ||
74 | +const SearchOptionContainer = styled.div` | ||
75 | + float: left; | ||
76 | +`; | ||
77 | + | ||
78 | +const SortOptionContainer = styled.div` | ||
79 | + float: left; | ||
80 | +`; | ||
81 | + | ||
82 | +const OptionContainer = styled.div` | ||
83 | + position: fixed; | ||
84 | + top: 130px; | ||
85 | + left: 650px; | ||
86 | +`; | ||
87 | + | ||
88 | +const UserContainer = styled.div` | ||
89 | + position: fixed; | ||
90 | + top: 35px; | ||
91 | + right: 0; | ||
92 | + padding-right: 20px; | ||
93 | +`; | ||
94 | + | ||
95 | +const AirContainer = styled.div` | ||
96 | + height: ${HeaderHeight}; | ||
97 | +`; | ||
98 | + | ||
99 | +const Header = () => { | ||
100 | + const [showModal, setShowModal] = useState(false); | ||
101 | + const openModal = () => { | ||
102 | + setShowModal(prev => !prev); | ||
103 | + }; | ||
104 | + const [setQuery] = useState(''); | ||
105 | + const history = useHistory(); | ||
106 | + const onMainClick = () => { | ||
107 | + setQuery(''); | ||
108 | + history.push(''); | ||
109 | + }; | ||
110 | + | ||
111 | + return ( | ||
112 | + <> | ||
113 | + <MainContainer> | ||
114 | + <HeaderTop /> | ||
115 | + <LogoContainer onClick={onMainClick}>로고</LogoContainer> | ||
116 | + <SearchContainer> | ||
117 | + <DropDownButton | ||
118 | + color="blue" | ||
119 | + float="left" | ||
120 | + fontsize="20px" | ||
121 | + height="34px" | ||
122 | + > | ||
123 | + 전체 | ||
124 | + </DropDownButton> | ||
125 | + <InputBlock color="blue" size="14px" float="left" width="400px"> | ||
126 | + <input /> | ||
127 | + </InputBlock> | ||
128 | + <SearchBox color="blue" size="50px" /> | ||
129 | + </SearchContainer> | ||
130 | + <MenuContainer> | ||
131 | + <ul> | ||
132 | + <SLink activeClassName="active" to="categori0"> | ||
133 | + 전체 | ||
134 | + </SLink> | ||
135 | + <SLink to="/categori1">개인</SLink> | ||
136 | + <SLink to="/categori2">부서</SLink> | ||
137 | + </ul> | ||
138 | + </MenuContainer> | ||
139 | + <OptionContainer> | ||
140 | + <SearchOptionContainer onClick={openModal}> | ||
141 | + <Button color="white">고급 검색</Button> | ||
142 | + </SearchOptionContainer> | ||
143 | + <Modal showModal={showModal} setShowModal={setShowModal} /> | ||
144 | + <SortOptionContainer> | ||
145 | + <DropDownButton | ||
146 | + color="white" | ||
147 | + width="80px" | ||
148 | + fontsize="15px" | ||
149 | + height="28px" | ||
150 | + > | ||
151 | + 정렬 | ||
152 | + </DropDownButton> | ||
153 | + </SortOptionContainer> | ||
154 | + </OptionContainer> | ||
155 | + <UserContainer> | ||
156 | + <Button color="white" width="100px" height="50px" fontsize="20px"> | ||
157 | + 사용자 님 | ||
158 | + </Button> | ||
159 | + </UserContainer> | ||
160 | + </MainContainer> | ||
161 | + <AirContainer /> | ||
162 | + </> | ||
163 | + ); | ||
164 | +}; | ||
165 | +export default Header; |
frontend/src/components/SearchOptionModal.js
0 → 100644
1 | +import React, { useRef } from 'react'; | ||
2 | +import styled from 'styled-components'; | ||
3 | +import Button from './common/Button'; | ||
4 | +import Input from './common/Input'; | ||
5 | + | ||
6 | +const Background = styled.div` | ||
7 | + position: fixed; | ||
8 | + display: flex; | ||
9 | + justify-content: center; | ||
10 | + align-items: center; | ||
11 | +`; | ||
12 | +const ModalWrapper = styled.div` | ||
13 | + width: 400px; | ||
14 | + height: 350px; | ||
15 | + box-shadow: 0 5px 16px rgba(0, 0, 0, 0.2); | ||
16 | + background: #fff; | ||
17 | + color: #000; | ||
18 | + display: grid; | ||
19 | + grid-template-columns: 1fr 1fr; | ||
20 | + position: relative; | ||
21 | + z-index: 10; | ||
22 | + border-radius: 10px; | ||
23 | +`; | ||
24 | + | ||
25 | +const ModalContent = styled.div` | ||
26 | + line-height: 1.8; | ||
27 | + color: #141414; | ||
28 | + p { | ||
29 | + margin-bottom: 1rem; | ||
30 | + } | ||
31 | + align-content: left; | ||
32 | +`; | ||
33 | + | ||
34 | +const SearchWrap = styled.div` | ||
35 | + position: fixed; | ||
36 | + top: 50%; | ||
37 | + right: 43%; | ||
38 | +`; | ||
39 | + | ||
40 | +const CloseWrap = styled.div` | ||
41 | + position: fixed; | ||
42 | + top: 50%; | ||
43 | + right: 32%; | ||
44 | +`; | ||
45 | + | ||
46 | +const StandardWrap = styled.div` | ||
47 | + width: 50px; | ||
48 | + position: fixed; | ||
49 | + top: 18%; | ||
50 | + right: 43%; | ||
51 | +`; | ||
52 | + | ||
53 | +const AdvancedWrap = styled.div` | ||
54 | + width: 50px; | ||
55 | + position: fixed; | ||
56 | + top: 27%; | ||
57 | + right: 43%; | ||
58 | +`; | ||
59 | + | ||
60 | +const TextWrap = styled.div` | ||
61 | + position: fixed; | ||
62 | + width: 340px; | ||
63 | + top: ${props => props.top}; | ||
64 | + right: ${props => props.right}; | ||
65 | + border-bottom: 2px solid #dee2e6; | ||
66 | + padding-left: 20px; | ||
67 | + padding-bottom: ${props => props.bottom}; | ||
68 | +`; | ||
69 | + | ||
70 | +const Modal = ({ showModal, setShowModal }) => { | ||
71 | + const modalRef = useRef(); | ||
72 | + const closeModal = e => { | ||
73 | + if (modalRef.current === e.target) { | ||
74 | + setShowModal(false); | ||
75 | + } | ||
76 | + }; | ||
77 | + | ||
78 | + return ( | ||
79 | + <> | ||
80 | + {showModal ? ( | ||
81 | + <Background onClick={closeModal}> | ||
82 | + <ModalWrapper> | ||
83 | + <ModalContent> | ||
84 | + <TextWrap top="18.5%" right="28.5%" bottom="19px"> | ||
85 | + 기본검색 | ||
86 | + </TextWrap> | ||
87 | + <StandardWrap> | ||
88 | + <Input float="left" color="blue" width="140px" size="10px" /> | ||
89 | + </StandardWrap> | ||
90 | + <TextWrap top="27%" right="28.5%" bottom="137px"> | ||
91 | + 고급검색 | ||
92 | + </TextWrap> | ||
93 | + <AdvancedWrap> | ||
94 | + <Input float="left" color="blue" width="140px" size="10px" /> | ||
95 | + <br /> <br /> | ||
96 | + <Input float="left" color="blue" width="140px" size="10px" /> | ||
97 | + <br /> <br /> | ||
98 | + <Input float="left" color="blue" width="140px" size="10px" /> | ||
99 | + </AdvancedWrap> | ||
100 | + </ModalContent> | ||
101 | + <CloseWrap onClick={() => setShowModal(prev => !prev)}> | ||
102 | + <Button width="100px" color="blue"> | ||
103 | + 닫기 | ||
104 | + </Button> | ||
105 | + </CloseWrap> | ||
106 | + <SearchWrap> | ||
107 | + <Button width="100px" color="gray"> | ||
108 | + 검색 | ||
109 | + </Button> | ||
110 | + </SearchWrap> | ||
111 | + </ModalWrapper> | ||
112 | + </Background> | ||
113 | + ) : null} | ||
114 | + </> | ||
115 | + ); | ||
116 | +}; | ||
117 | +export default Modal; |
... | @@ -10,22 +10,28 @@ const DropDownBlock = styled.div` | ... | @@ -10,22 +10,28 @@ const DropDownBlock = styled.div` |
10 | const DropDownHeader = styled.button` | 10 | const DropDownHeader = styled.button` |
11 | margin-bottom: 0.8em; | 11 | margin-bottom: 0.8em; |
12 | padding: 0.4em; | 12 | padding: 0.4em; |
13 | - box-shadow: 0 2px 3px rgba(0, 0, 0, 0.15); | 13 | + width: ${props => props.width || '100px'}; |
14 | - font-weight: 500; | 14 | + line-height: ${props => props.height || '30px'}; |
15 | - font-size: ${props => props.size}; | 15 | + padding-right: 30px; |
16 | - border: 2px solid ${props => dropdownHeaderColorMap[props.color].borderColor}; | 16 | + font-size: ${props => props.fontsize || '20px'}; |
17 | color: ${props => dropdownHeaderColorMap[props.color].color}; | 17 | color: ${props => dropdownHeaderColorMap[props.color].color}; |
18 | background-color: ${props => dropdownHeaderColorMap[props.color].background}; | 18 | background-color: ${props => dropdownHeaderColorMap[props.color].background}; |
19 | &:hover { | 19 | &:hover { |
20 | background-color: ${props => | 20 | background-color: ${props => |
21 | dropdownHeaderColorMap[props.color].hoverBackground}; | 21 | dropdownHeaderColorMap[props.color].hoverBackground}; |
22 | } | 22 | } |
23 | + border: 1px ${props => dropdownHeaderColorMap[props.color].background}; | ||
23 | `; | 24 | `; |
24 | 25 | ||
25 | -const DropDown = ({ children, float, color, size }) => { | 26 | +const DropDown = ({ children, float, color, fontsize, width, height }) => { |
26 | return ( | 27 | return ( |
27 | - <DropDownBlock float={float} color={color} size={size}> | 28 | + <DropDownBlock float={float} color={color}> |
28 | - <DropDownHeader color={color} size={size}> | 29 | + <DropDownHeader |
30 | + color={color} | ||
31 | + fontsize={fontsize} | ||
32 | + width={width} | ||
33 | + height={height} | ||
34 | + > | ||
29 | {children} | 35 | {children} |
30 | </DropDownHeader> | 36 | </DropDownHeader> |
31 | </DropDownBlock> | 37 | </DropDownBlock> | ... | ... |
1 | -import React from 'react'; | 1 | +import React, { useState } from 'react'; |
2 | import styled from 'styled-components'; | 2 | import styled from 'styled-components'; |
3 | +import { useHistory } from 'react-router-dom'; | ||
3 | import { inputColorMap } from '../../lib/styles/palette'; | 4 | import { inputColorMap } from '../../lib/styles/palette'; |
4 | 5 | ||
5 | const InputBlock = styled.div` | 6 | const InputBlock = styled.div` |
6 | input { | 7 | input { |
7 | - padding: 20px; | 8 | + padding: ${props => props.size}; |
8 | - padding-right: 200px; | 9 | + padding-right: ${props => props.width}; |
9 | color: ${props => inputColorMap[props.color].color}; | 10 | color: ${props => inputColorMap[props.color].color}; |
10 | box-shadow: 2px 3px 28px 1px rgba(0, 0, 0, 0.1); | 11 | box-shadow: 2px 3px 28px 1px rgba(0, 0, 0, 0.1); |
11 | border: 3px solid ${props => inputColorMap[props.color].borderColor}; | 12 | border: 3px solid ${props => inputColorMap[props.color].borderColor}; |
... | @@ -20,10 +21,27 @@ const InputBlock = styled.div` | ... | @@ -20,10 +21,27 @@ const InputBlock = styled.div` |
20 | float: ${props => props.float || ''}; | 21 | float: ${props => props.float || ''}; |
21 | `; | 22 | `; |
22 | 23 | ||
23 | -const Input = ({ children, color, size, float }) => { | 24 | +const Input = ({ color, size, float, width }) => { |
25 | + const [query, setQuery] = useState(''); | ||
26 | + const history = useHistory(); | ||
24 | return ( | 27 | return ( |
25 | - <InputBlock color={color} size={size} float={float}> | 28 | + <InputBlock color={color} size={size} float={float} width={width}> |
26 | - <input placeholder={children} color={color} /> | 29 | + <input |
30 | + placeholder="내용을 입력해 주세요." | ||
31 | + type="text" | ||
32 | + value={query} | ||
33 | + onChange={e => setQuery(e.target.value)} | ||
34 | + onKeyPress={e => { | ||
35 | + if (e.key === 'Enter') { | ||
36 | + if (query === '') { | ||
37 | + alert('검색어를 입력 해 주세요.'); | ||
38 | + return; | ||
39 | + } | ||
40 | + const params = new URLSearchParams({ query }); | ||
41 | + history.push(`?${params.toString()}`); | ||
42 | + } | ||
43 | + }} | ||
44 | + /> | ||
27 | </InputBlock> | 45 | </InputBlock> |
28 | ); | 46 | ); |
29 | }; | 47 | }; | ... | ... |
... | @@ -14,6 +14,7 @@ const ButtonBlock = styled.button` | ... | @@ -14,6 +14,7 @@ const ButtonBlock = styled.button` |
14 | } | 14 | } |
15 | color: ${props => searchBoxColorMap[props.color].color}; | 15 | color: ${props => searchBoxColorMap[props.color].color}; |
16 | float: ${props => props.float || ''}; | 16 | float: ${props => props.float || ''}; |
17 | + border: 1px ${props => searchBoxColorMap[props.color].background}; | ||
17 | `; | 18 | `; |
18 | 19 | ||
19 | const SearchBox = ({ color, float, size }) => { | 20 | const SearchBox = ({ color, float, size }) => { | ... | ... |
... | @@ -40,6 +40,16 @@ export const buttonColorMap = { | ... | @@ -40,6 +40,16 @@ export const buttonColorMap = { |
40 | color: 'white', | 40 | color: 'white', |
41 | hoverBackground: palette.blue5, | 41 | hoverBackground: palette.blue5, |
42 | }, | 42 | }, |
43 | + gray: { | ||
44 | + background: palette.gray2, | ||
45 | + color: 'black', | ||
46 | + hoverBackground: palette.gray5, | ||
47 | + }, | ||
48 | + white: { | ||
49 | + background: 'white', | ||
50 | + color: 'black', | ||
51 | + hoverBackground: palette.gray2, | ||
52 | + }, | ||
43 | }; | 53 | }; |
44 | 54 | ||
45 | export const inputColorMap = { | 55 | export const inputColorMap = { |
... | @@ -65,6 +75,11 @@ export const dropdownHeaderColorMap = { | ... | @@ -65,6 +75,11 @@ export const dropdownHeaderColorMap = { |
65 | hoverBackground: palette.blue5, | 75 | hoverBackground: palette.blue5, |
66 | borderColor: palette.blue8, | 76 | borderColor: palette.blue8, |
67 | }, | 77 | }, |
78 | + white: { | ||
79 | + background: 'white', | ||
80 | + color: 'black', | ||
81 | + hoverBackground: palette.gray2, | ||
82 | + }, | ||
68 | }; | 83 | }; |
69 | 84 | ||
70 | export const searchBoxColorMap = { | 85 | export const searchBoxColorMap = { | ... | ... |
-
Please register or login to post a comment