Skip to content

Commit 688cc06

Browse files
authored
Merge pull request velopert#127 from velopert/fix/use-common-header
Fix/use common header
2 parents a17728e + d3c7ed8 commit 688cc06

File tree

11 files changed

+138
-501
lines changed

11 files changed

+138
-501
lines changed

src/components/main/FloatingHomeHeader.tsx renamed to src/components/base/FloatingHeader.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import React, { useEffect, useCallback, useRef, useState } from 'react';
22
import styled from 'styled-components';
3-
import MainHeader from './MainHeader';
3+
import Header from './Header';
44
import HomeTab from '../home/HomeTab';
5-
import MainResponsive from './MainResponsive';
5+
import MainResponsive from '../main/MainResponsive';
66
import { getScrollTop } from '../../lib/utils';
77
import { Route } from 'react-router-dom';
88
import ReadingListTab from '../readingList/ReadingListTab';
99

10-
export type FloatingMainHeaderProps = {};
10+
export type FloatingHeaderProps = {};
1111

12-
function FloatingMainHeader(props: FloatingMainHeaderProps) {
12+
function FloatingHeader(props: FloatingHeaderProps) {
1313
const [visible, setVisible] = useState(false);
1414
const blockRef = useRef<HTMLDivElement>(null);
1515
const [height, setHeight] = useState(0);
@@ -79,7 +79,7 @@ function FloatingMainHeader(props: FloatingMainHeaderProps) {
7979
}
8080
ref={blockRef}
8181
>
82-
<MainHeader />
82+
<Header />
8383
<Route
8484
path={['/', '/:mode(recent|trending)']}
8585
render={() => (
@@ -121,4 +121,4 @@ const StyledMainResponsive = styled(MainResponsive)`
121121
margin-top: 1.5rem;
122122
`;
123123

124-
export default FloatingMainHeader;
124+
export default FloatingHeader;

src/components/base/Header.tsx

Lines changed: 106 additions & 177 deletions
Original file line numberDiff line numberDiff line change
@@ -1,121 +1,23 @@
11
import React, { useRef, useCallback } from 'react';
2-
import styled, { css } from 'styled-components';
2+
import styled from 'styled-components';
3+
import { SearchIcon2 } from '../../static/svg';
34
import RoundButton from '../common/RoundButton';
4-
import { CurrentUser } from '../../lib/graphql/user';
5+
import MainResponsive from '../main/MainResponsive';
6+
import useHeader from './hooks/useHeader';
57
import HeaderUserIcon from './HeaderUserIcon';
68
import useToggle from '../../lib/hooks/useToggle';
79
import HeaderUserMenu from './HeaderUserMenu';
8-
import { logout } from '../../lib/api/auth';
9-
import storage from '../../lib/storage';
10-
import { UserLogo } from '../../modules/header';
11-
import HeaderLogo from './HeaderLogo';
12-
import media from '../../lib/styles/media';
13-
import { SearchIcon2 } from '../../static/svg';
1410
import { Link } from 'react-router-dom';
15-
import MainResponsive from '../main/MainResponsive';
16-
17-
const HeaderBlock = styled.div<{ floating: boolean }>`
18-
width: 100%;
19-
.wrapper {
20-
/* width: 1200px; */
21-
width: 100%;
22-
height: 4rem;
23-
/* padding-left: 1rem;
24-
padding-right: 1rem; */
25-
display: flex;
26-
justify-content: space-between;
27-
align-items: center;
28-
29-
.search {
30-
display: none;
31-
margin-right: 1rem;
32-
}
33-
34-
.right {
35-
display: flex;
36-
align-items: center;
37-
}
38-
39-
${media.large} {
40-
/* width: 1024px; */
41-
}
42-
${media.medium} {
43-
/* width: 100%; */
44-
.write-button {
45-
display: none;
46-
}
47-
.search {
48-
display: block;
49-
}
50-
}
51-
${media.small} {
52-
height: 3.5rem;
53-
54-
.login-button {
55-
font-size: 0.875rem;
56-
padding-left: 0.75rem;
57-
padding-right: 0.75rem;
58-
}
59-
}
60-
61-
.logged-in {
62-
position: relative;
63-
display: flex;
64-
align-items: center;
65-
}
66-
}
67-
68-
${props =>
69-
props.floating &&
70-
css`
71-
z-index: 10;
72-
position: fixed;
73-
top: 0;
74-
background: rgba(255, 255, 255, 1);
75-
box-shadow: 0px 0 8px rgba(0, 0, 0, 0.08);
76-
`}
77-
`;
78-
79-
const Placeholder = styled.div`
80-
width: 100%;
81-
height: 5rem;
82-
${media.small} {
83-
height: 3.5rem;
84-
}
85-
`;
11+
import media from '../../lib/styles/media';
12+
import HeaderLogo from './HeaderLogo';
8613

87-
interface HeaderProps {
88-
floating: boolean;
89-
floatingMargin: number;
90-
onLoginClick: () => void;
91-
user: CurrentUser | null;
92-
custom: boolean;
93-
userLogo: UserLogo | null;
94-
velogUsername: string | null;
95-
isSearch: boolean;
96-
}
14+
export type MainHeaderProps = {};
9715

98-
const Header: React.FC<HeaderProps> = ({
99-
floating,
100-
floatingMargin,
101-
onLoginClick,
102-
user,
103-
custom,
104-
userLogo,
105-
velogUsername,
106-
isSearch,
107-
}) => {
16+
function Header(props: MainHeaderProps) {
17+
const { user, onLoginClick, onLogout, customHeader } = useHeader();
10818
const [userMenu, toggleUserMenu] = useToggle(false);
10919
const ref = useRef<HTMLDivElement>(null);
11020

111-
const onLogout = useCallback(async () => {
112-
try {
113-
await logout();
114-
} catch {}
115-
storage.removeItem('CURRENT_USER');
116-
window.location.href = '/';
117-
}, []);
118-
11921
const onOutsideClick = useCallback(
12022
(e: React.MouseEvent) => {
12123
if (!ref.current) return;
@@ -125,78 +27,105 @@ const Header: React.FC<HeaderProps> = ({
12527
[toggleUserMenu],
12628
);
12729

30+
const urlForSearch = customHeader.custom
31+
? `/search?username=${customHeader.username}`
32+
: '/search';
33+
12834
return (
129-
<>
130-
<HeaderBlock
131-
floating={floating}
132-
style={{ marginTop: floating ? floatingMargin : 0 }}
133-
data-testid="Header"
134-
>
135-
<MainResponsive>
136-
<div className="wrapper">
137-
<div className="brand">
138-
<HeaderLogo
139-
custom={custom}
140-
userLogo={userLogo}
141-
velogUsername={velogUsername}
142-
/>
143-
</div>
144-
<div className="right">
145-
{/* {velogUsername ? (
146-
<SearchIcon2 className="search" />
147-
) : (
148-
<Link to="/search">
149-
<SearchIcon2 className="search" />
150-
</Link>
151-
)} */}
152-
{!isSearch && (
153-
<Link
154-
to={
155-
velogUsername
156-
? `/search?username=${velogUsername}`
157-
: '/search'
158-
}
159-
>
160-
<SearchIcon2 className="search" />
161-
</Link>
162-
)}
163-
{user ? (
164-
<div className="logged-in">
165-
<RoundButton
166-
border
167-
color="darkGray"
168-
style={{ marginRight: '1.25rem' }}
169-
to="/write"
170-
className="write-button"
171-
>
172-
새 글 작성
173-
</RoundButton>
174-
<div ref={ref}>
175-
<HeaderUserIcon user={user} onClick={toggleUserMenu} />
176-
</div>
177-
<HeaderUserMenu
178-
onClose={onOutsideClick}
179-
username={user.username}
180-
onLogout={onLogout}
181-
visible={userMenu}
182-
/>
183-
</div>
184-
) : (
185-
<RoundButton
186-
color="darkGray"
187-
onClick={onLoginClick}
188-
className="login-button"
189-
>
190-
로그인
191-
</RoundButton>
192-
)}
35+
<Block>
36+
<Inner>
37+
<HeaderLogo
38+
custom={customHeader.custom}
39+
userLogo={customHeader.userLogo}
40+
username={customHeader.username}
41+
/>
42+
43+
{user ? (
44+
<Right>
45+
<SearchButton to={urlForSearch}>
46+
<SearchIcon2 />
47+
</SearchButton>
48+
<RoundButton
49+
border
50+
color="darkGray"
51+
style={{ marginRight: '1.25rem' }}
52+
to="/write"
53+
className="write-button"
54+
>
55+
새 글 작성
56+
</RoundButton>
57+
58+
<div ref={ref}>
59+
<HeaderUserIcon user={user} onClick={toggleUserMenu} />
19360
</div>
194-
</div>
195-
</MainResponsive>
196-
</HeaderBlock>
197-
{floating && <Placeholder />}
198-
</>
61+
<HeaderUserMenu
62+
onClose={onOutsideClick}
63+
onLogout={onLogout}
64+
username={user.username}
65+
visible={userMenu}
66+
/>
67+
</Right>
68+
) : (
69+
<Right>
70+
<SearchButton to={urlForSearch}>
71+
<SearchIcon2 />
72+
</SearchButton>
73+
<RoundButton color="darkGray" onClick={onLoginClick}>
74+
로그인
75+
</RoundButton>
76+
</Right>
77+
)}
78+
</Inner>
79+
</Block>
19980
);
200-
};
81+
}
82+
83+
const Block = styled.div`
84+
height: 4rem;
85+
`;
86+
87+
const StyledLink = styled(Link)`
88+
display: flex;
89+
align-items: center;
90+
`;
91+
92+
const SearchButton = styled(Link)`
93+
display: flex;
94+
align-items: center;
95+
justify-content: center;
96+
background: transparent;
97+
border: none;
98+
width: 2.5rem;
99+
height: 2.5rem;
100+
outline: none;
101+
border-radius: 50%;
102+
cursor: pointer;
103+
&:hover {
104+
background: rgba(0, 0, 0, 0.045);
105+
}
106+
svg {
107+
width: 1.125rem;
108+
height: 1.125rem;
109+
}
110+
margin-right: 0.75rem;
111+
`;
112+
113+
const Inner = styled(MainResponsive)`
114+
height: 100%;
115+
display: flex;
116+
align-items: center;
117+
justify-content: space-between;
118+
`;
119+
120+
const Right = styled.div`
121+
display: flex;
122+
align-items: center;
123+
position: relative;
124+
.write-button {
125+
${media.medium} {
126+
display: none;
127+
}
128+
}
129+
`;
201130

202131
export default Header;

src/components/base/HeaderLogo.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ import media from '../../lib/styles/media';
1010
export interface HeaderLogoProps {
1111
custom: boolean;
1212
userLogo: UserLogo | null;
13-
velogUsername: string | null;
13+
username: string | null;
1414
}
1515

1616
const HeaderLogo: React.FC<HeaderLogoProps> = ({
1717
custom,
1818
userLogo,
19-
velogUsername,
19+
username,
2020
}) => {
2121
if (!custom) {
2222
return (
@@ -27,16 +27,16 @@ const HeaderLogo: React.FC<HeaderLogoProps> = ({
2727
</HeaderLogoBlock>
2828
);
2929
}
30-
if (!userLogo) return null;
31-
if (!velogUsername) return null;
32-
const velogPath = `/@${velogUsername}`;
30+
if (!userLogo) return <div />;
31+
if (!username) return <div />;
32+
const velogPath = `/@${username}`;
3333
return (
3434
<HeaderLogoBlock>
3535
<VelogLogoLink to="/">
3636
<VelogIcon />
3737
</VelogLogoLink>
3838
<Link to={velogPath}>
39-
{userLogo.title || createFallbackTitle(velogUsername)}
39+
{userLogo.title || createFallbackTitle(username)}
4040
</Link>
4141
</HeaderLogoBlock>
4242
);

0 commit comments

Comments
 (0)