From 764d718ecdf7e5479b8492d31f7fd37f90479e80 Mon Sep 17 00:00:00 2001 From: saseungmin Date: Fri, 4 Dec 2020 01:25:17 +0900 Subject: [PATCH] [improve & Refactor] common component buttons and Links - create styled components - improve for Header Links - improve for introduce and main Buttons --- src/App.test.jsx | 2 + src/components/common/DateTimeChange.jsx | 2 +- src/components/common/Header.jsx | 32 ++++---- .../introduce/ApplyStatusButton.jsx | 45 ++++++++++- .../introduce/StudyIntroduceForm.jsx | 26 ------- src/components/main/StudyGroups.jsx | 25 ++---- src/containers/common/HeaderContainer.jsx | 6 +- .../common/HeaderContainer.test.jsx | 11 --- .../write/WriteButtonsContainer.jsx | 12 ++- .../write/WriteButtonsContainer.test.jsx | 8 +- src/index.css | 4 +- src/pages/WritePage.test.jsx | 2 +- src/styles/Button.jsx | 78 +++++++++++++++++++ src/styles/palette.js | 5 ++ 14 files changed, 160 insertions(+), 98 deletions(-) create mode 100644 src/styles/Button.jsx diff --git a/src/App.test.jsx b/src/App.test.jsx index 00f7daa..496f11c 100644 --- a/src/App.test.jsx +++ b/src/App.test.jsx @@ -41,6 +41,7 @@ describe('App', () => { userEmail: '', password: '', }, + user: given.user, }, })); }); @@ -71,6 +72,7 @@ describe('App', () => { context('with path /write', () => { given('group', () => (null)); + given('user', () => ('user1')); it('renders the study write page', () => { const { container } = renderApp({ path: '/write' }); diff --git a/src/components/common/DateTimeChange.jsx b/src/components/common/DateTimeChange.jsx index bb43a5e..d51f7e5 100644 --- a/src/components/common/DateTimeChange.jsx +++ b/src/components/common/DateTimeChange.jsx @@ -48,7 +48,7 @@ const DateTimeChange = ({ group, page, time }) => { return ( - {applyEndTime} + {applyEndTime}  모집 마감 ); diff --git a/src/components/common/Header.jsx b/src/components/common/Header.jsx index d72b8c3..f77b4d2 100644 --- a/src/components/common/Header.jsx +++ b/src/components/common/Header.jsx @@ -6,6 +6,7 @@ import styled from '@emotion/styled'; import Responsive from '../../styles/Responsive'; import palette from '../../styles/palette'; +import Button from '../../styles/Button'; const HeaderWrapper = styled.div` position: fixed; @@ -19,8 +20,11 @@ const Wrapper = styled(Responsive)` display: flex; align-items: center; justify-content: space-between; - div{ - margin-right: 4rem; +`; + +const UserStatusWrapper = styled.div` + span { + margin-right: 1rem; } `; @@ -29,16 +33,6 @@ const TitleWrapper = styled(Link)` font-size: 1.8rem; `; -const LinkWrapper = styled(Link)` - :first-of-type{ - margin-right: 1rem; - } - :hover { - color: ${palette.gray[6]}; - } - font-weight: bold; -`; - const Spacer = styled.div` height: 6rem; `; @@ -49,19 +43,19 @@ const Header = ({ user, onLogout }) => ( 제목(미정) {user ? ( -
+ {user} - -
+ + ) : (
- 로그인 - 회원가입 + +
)}
diff --git a/src/components/introduce/ApplyStatusButton.jsx b/src/components/introduce/ApplyStatusButton.jsx index e9741ef..3c71593 100644 --- a/src/components/introduce/ApplyStatusButton.jsx +++ b/src/components/introduce/ApplyStatusButton.jsx @@ -2,7 +2,46 @@ import React from 'react'; import styled from '@emotion/styled'; -const ApplyStatusButtonWrapper = styled.button``; +import palette from '../../styles/palette'; + +const ApplyStatusButtonWrapper = styled.button` + display: inline-flex; + align-items: center; + margin: .5rem 0 .5rem 0; + padding: 0.25rem 5rem; + font-size: 1.5em; + line-height: 0; + font-family: 'Gamja Flower', cursive; + border-radius: 0.4rem; + border: none; + outline: none; + + &.deadline { + cursor: not-allowed; + background: ${palette.gray[3]}; + color: ${palette.gray[5]}; + } + + &.apply-complete { + background: ${palette.gray[1]}; + border: 2px solid #a5d8ff; + color: #74c0fc; + } + + &.apply { + color: white; + cursor: pointer; + background: ${palette.teal[5]}; + &:hover{ + background: ${palette.teal[4]}; + } + } + + &.no-login{ + cursor: not-allowed; + color: ${palette.gray[5]}; + } +`; const ApplyStatusButton = ({ timeStatus, onApply, user, applyStatus, @@ -11,7 +50,7 @@ const ApplyStatusButton = ({ return ( 신청 완료 @@ -33,7 +72,7 @@ const ApplyStatusButton = ({ return ( 로그인 후 신청 가능합니다. diff --git a/src/components/introduce/StudyIntroduceForm.jsx b/src/components/introduce/StudyIntroduceForm.jsx index 0d124e7..6108918 100644 --- a/src/components/introduce/StudyIntroduceForm.jsx +++ b/src/components/introduce/StudyIntroduceForm.jsx @@ -26,32 +26,6 @@ const IntroduceHeaderWrapper = styled.div` line-height: 1.5; margin: 0; } - // TODO: 추후 공통 버튼 style component로 변경 - button { - display: inline-flex; - align-items: center; - margin: .5rem 0 .5rem 0; - padding: 0.25rem 5rem; - font-size: 1.5em; - line-height: 0; - font-family: 'Gamja Flower', cursive; - border-radius: 0.4rem; - border: none; - outline: none; - } - .deadline{ - cursor: not-allowed; - background: ${palette.gray[3]}; - color: ${palette.gray[5]}; - } - .apply{ - color: white; - cursor: pointer; - background: ${palette.teal[5]}; - &:hover{ - background: ${palette.teal[4]}; - } - } `; const IntroduceReferenceWrapper = styled.div` diff --git a/src/components/main/StudyGroups.jsx b/src/components/main/StudyGroups.jsx index 1017b0e..96f906b 100644 --- a/src/components/main/StudyGroups.jsx +++ b/src/components/main/StudyGroups.jsx @@ -1,12 +1,9 @@ import React from 'react'; -import { Link } from 'react-router-dom'; - import styled from '@emotion/styled'; -import palette from '../../styles/palette'; - import StudyGroup from './StudyGroup'; +import Button from '../../styles/Button'; const StudyGroupsWrapper = styled.div` display: flex; @@ -19,20 +16,6 @@ const TitleHeader = styled.div` display: flex; justify-content: space-between; align-items: center; - // TODO: Link 공통 style component 만들기 - a { - margin-right: 4rem; - padding: .6rem .9rem .6rem .9rem; - border: 1px solid ${palette.gray[7]}; - background: white; - color: ${palette.gray[7]}; - font-weight: bold; - border-radius: .7rem; - :hover { - color: white; - background: ${palette.gray[7]}; - } - } `; const StudyGroups = ({ groups, realTime, user }) => ( @@ -40,7 +23,11 @@ const StudyGroups = ({ groups, realTime, user }) => (

지금 바로 시작하세요!

{user && ( - 스터디 개설하기 + )}
diff --git a/src/containers/common/HeaderContainer.jsx b/src/containers/common/HeaderContainer.jsx index bd23834..5aea97f 100644 --- a/src/containers/common/HeaderContainer.jsx +++ b/src/containers/common/HeaderContainer.jsx @@ -1,6 +1,5 @@ import React, { useCallback } from 'react'; -import { useHistory } from 'react-router-dom'; import { useDispatch, useSelector } from 'react-redux'; import { getAuth } from '../../util/utils'; @@ -10,15 +9,12 @@ import Header from '../../components/common/Header'; const HeaderContainer = () => { const dispatch = useDispatch(); - const history = useHistory(); const user = useSelector(getAuth('user')); const onLogout = useCallback(() => { dispatch(requestLogout()); - - history.push('/'); - }, [dispatch, history]); + }, [dispatch]); return (
({ - ...jest.requireActual('react-router-dom'), - useHistory() { - return { push: mockPush }; - }, -})); - describe('HeaderContainer', () => { const dispatch = jest.fn(); beforeEach(() => { dispatch.mockClear(); - mockPush.mockClear(); useDispatch.mockImplementation(() => dispatch); @@ -58,7 +48,6 @@ describe('HeaderContainer', () => { fireEvent.click(button); expect(dispatch).toBeCalled(); - expect(mockPush).toBeCalledWith('/'); }); }); diff --git a/src/containers/write/WriteButtonsContainer.jsx b/src/containers/write/WriteButtonsContainer.jsx index 593e542..f59be4a 100644 --- a/src/containers/write/WriteButtonsContainer.jsx +++ b/src/containers/write/WriteButtonsContainer.jsx @@ -11,9 +11,7 @@ import WriteButtons from '../../components/write/WriteButtons'; const isCheckApplyEndDate = (applyDate) => Date.now() - applyDate >= 0; -const { - NO_INPUT, NO_TAG, FAST_APPLY_DEADLINE, NO_LOGGED_IN, -} = ERROR_MESSAGE; +const { NO_INPUT, NO_TAG, FAST_APPLY_DEADLINE } = ERROR_MESSAGE; const WriteButtonsContainer = () => { const [error, setError] = useState(null); @@ -31,13 +29,13 @@ const WriteButtonsContainer = () => { const applyEndTime = new Date(applyEndDate).getTime(); - const onSubmit = () => { - // TODO: 모달창으로 처리 후 redirection 시키기? + useEffect(() => { if (!user) { - setError(NO_LOGGED_IN); - return; + history.push('/'); } + }, [user, history]); + const onSubmit = () => { if (isCheckValidate([title, applyEndDate, personnel])) { setError(NO_INPUT); return; diff --git a/src/containers/write/WriteButtonsContainer.test.jsx b/src/containers/write/WriteButtonsContainer.test.jsx index ff72bbd..f67528d 100644 --- a/src/containers/write/WriteButtonsContainer.test.jsx +++ b/src/containers/write/WriteButtonsContainer.test.jsx @@ -185,12 +185,10 @@ describe('WriteButtonsContainer', () => { ], })); - it('renders error message "Please use after logging in"', () => { - const { container, getByText } = renderWriteButtonsContainer(); + it('go to redirection main page', () => { + renderWriteButtonsContainer(); - fireEvent.click(getByText('등록하기')); - - expect(container).toHaveTextContent('로그인 후 이용하세요.'); + expect(mockPush).toBeCalledWith('/'); }); }); }); diff --git a/src/index.css b/src/index.css index 159198d..8c71bdd 100644 --- a/src/index.css +++ b/src/index.css @@ -4,10 +4,12 @@ font-family: 'Gamja Flower', cursive; font-family: 'Nanum Pen Script', cursive; */ @import url('//cdn.jsdelivr.net/gh/wan2land/d2coding/d2coding-full.css'); - +@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300&display=swap'); +/* font-family: 'Noto Sans KR', sans-serif; */ * { box-sizing: inherit; + font-family: 'Noto Sans KR', sans-serif; } a { diff --git a/src/pages/WritePage.test.jsx b/src/pages/WritePage.test.jsx index c3fb288..90e4900 100644 --- a/src/pages/WritePage.test.jsx +++ b/src/pages/WritePage.test.jsx @@ -21,7 +21,7 @@ describe('WritePage', () => { }, }, authReducer: { - user: null, + user: 'user1', }, })); }); diff --git a/src/styles/Button.jsx b/src/styles/Button.jsx new file mode 100644 index 0000000..d03fabe --- /dev/null +++ b/src/styles/Button.jsx @@ -0,0 +1,78 @@ +/* eslint-disable react/jsx-props-no-spreading */ +import React from 'react'; + +import { Link } from 'react-router-dom'; + +import styled from '@emotion/styled'; +import { css } from '@emotion/react'; + +import palette from './palette'; + +const ButtonWrapper = (props) => css` + border-radius: 4px; + font-size: 1rem; + font-weight: bold; + font-family: 'Noto Sans KR', sans-serif; + padding: 0.25rem 1rem; + color: ${palette.gray[7]}; + outline: none; + cursor: pointer; + border: 1px solid ${palette.gray[7]}; + background: white; + &:hover { + color: white; + background: ${palette.gray[7]}; + } + + ${props.warn + && css` + color: white; + padding: 0.15rem 0.9rem; + background: ${palette.warn[1]}; + border: 1px solid ${palette.warn[1]}; + &:hover { + background: white; + color: ${palette.warn[1]}; + border: 1px solid ${palette.warn[1]}; + } + `} + + ${props.success + && css` + color: white; + background: ${palette.teal[5]}; + border: 1px solid ${palette.teal[5]}; + &:hover { + background: white; + color: ${palette.teal[5]}; + border: 1px solid ${palette.teal[5]}; + } + `} +`; + +const StyledButton = styled.button` + ${ButtonWrapper} +`; +const StyledLink = styled(Link)` + ${ButtonWrapper} +`; + +const Button = (props) => { + const { to, success, warn } = props; + + return ( + <> + {to ? ( + + ) : ( + + )} + + ); +}; + +export default Button; diff --git a/src/styles/palette.js b/src/styles/palette.js index df2a8c3..6c79748 100644 --- a/src/styles/palette.js +++ b/src/styles/palette.js @@ -59,6 +59,11 @@ const palette = { '#6741d9', '#5f3dc4', ], + warn: [ + '#ffa8a8', + '#ff8787', + '#ff6b6b', + ], }; export default palette;