From 07ea00d12b74bdcab2a8c40bd592caf0cd6f0a1c Mon Sep 17 00:00:00 2001 From: saseungmin Date: Thu, 3 Dec 2020 00:09:22 +0900 Subject: [PATCH] [Improve] Change the hardcoded author ID - and Error handling if you are not logged in --- src/components/main/StudyGroups.jsx | 52 ++++- .../groups/StudyGroupsContainer.jsx | 2 + .../write/WriteButtonsContainer.jsx | 11 +- .../write/WriteButtonsContainer.test.jsx | 179 ++++++++++-------- src/pages/MainPage.jsx | 38 +--- src/pages/MainPage.test.jsx | 25 ++- src/reducers/slice.js | 13 +- src/util/messages.js | 1 + 8 files changed, 187 insertions(+), 134 deletions(-) diff --git a/src/components/main/StudyGroups.jsx b/src/components/main/StudyGroups.jsx index 53eb1d1..1017b0e 100644 --- a/src/components/main/StudyGroups.jsx +++ b/src/components/main/StudyGroups.jsx @@ -1,7 +1,11 @@ import React from 'react'; +import { Link } from 'react-router-dom'; + import styled from '@emotion/styled'; +import palette from '../../styles/palette'; + import StudyGroup from './StudyGroup'; const StudyGroupsWrapper = styled.div` @@ -11,16 +15,44 @@ const StudyGroupsWrapper = styled.div` align-content: space-between; `; -const StudyGroups = ({ groups, realTime }) => ( - - {groups.map((group) => ( - - ))} - +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 }) => ( + <> + +

지금 바로 시작하세요!

+ {user && ( + 스터디 개설하기 + )} +
+ + {groups.map((group) => ( + + ))} + + ); export default StudyGroups; diff --git a/src/containers/groups/StudyGroupsContainer.jsx b/src/containers/groups/StudyGroupsContainer.jsx index b0ab91a..2016417 100644 --- a/src/containers/groups/StudyGroupsContainer.jsx +++ b/src/containers/groups/StudyGroupsContainer.jsx @@ -18,6 +18,7 @@ const StudyGroupsContainer = () => { const dispatch = useDispatch(); const groups = useSelector(get('groups')); + const user = useSelector(get('user')); useInterval(() => { setRealTime(Date.now()); @@ -37,6 +38,7 @@ const StudyGroupsContainer = () => { return ( diff --git a/src/containers/write/WriteButtonsContainer.jsx b/src/containers/write/WriteButtonsContainer.jsx index c8864d7..f0feef2 100644 --- a/src/containers/write/WriteButtonsContainer.jsx +++ b/src/containers/write/WriteButtonsContainer.jsx @@ -11,7 +11,9 @@ import WriteButtons from '../../components/write/WriteButtons'; const isCheckApplyEndDate = (applyDate) => Date.now() - applyDate >= 0; -const { NO_INPUT, NO_TAG, FAST_APPLY_DEADLINE } = ERROR_MESSAGE; +const { + NO_INPUT, NO_TAG, FAST_APPLY_DEADLINE, NO_LOGGED_IN, +} = ERROR_MESSAGE; const WriteButtonsContainer = () => { const [error, setError] = useState(null); @@ -21,6 +23,7 @@ const WriteButtonsContainer = () => { const writeField = useSelector(get('writeField')); const groupId = useSelector(get('groupId')); + const user = useSelector(get('user')); const { title, applyEndDate, personnel, tags, @@ -29,6 +32,12 @@ const WriteButtonsContainer = () => { const applyEndTime = new Date(applyEndDate).getTime(); const onSubmit = () => { + // TODO: 모달창으로 처리 후 redirection 시키기? + if (!user) { + setError(NO_LOGGED_IN); + return; + } + 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 7db70e6..3b1bb1a 100644 --- a/src/containers/write/WriteButtonsContainer.test.jsx +++ b/src/containers/write/WriteButtonsContainer.test.jsx @@ -30,6 +30,7 @@ describe('WriteButtonsContainer', () => { useSelector.mockImplementation((state) => state({ writeField: given.writeField, groupId: given.groupId, + user: given.user, })); }); @@ -62,101 +63,131 @@ describe('WriteButtonsContainer', () => { }); describe('when click submit button', () => { - context('without input value null, so validation check success', () => { - given('writeField', () => (WRITE_FORM)); + context('with user', () => { + given('user', () => ('user')); - context('with group', () => { - given('groupId', () => ('1')); + context('without input value null, so validation check success', () => { + given('writeField', () => (WRITE_FORM)); - it('dispatch action writeStudyGroup event', () => { - const { getByText } = renderWriteButtonsContainer(); + context('with group', () => { + given('groupId', () => ('1')); - fireEvent.click(getByText('등록하기')); + it('dispatch action writeStudyGroup event', () => { + const { getByText } = renderWriteButtonsContainer(); - expect(dispatch).toBeCalledTimes(1); + fireEvent.click(getByText('등록하기')); - expect(mockPush).toBeCalledWith('/introduce/1'); + expect(dispatch).toBeCalledTimes(1); + + expect(mockPush).toBeCalledWith('/introduce/1'); + }); }); - }); - context('without group', () => { - given('groupId', () => (null)); + context('without group', () => { + given('groupId', () => (null)); - it('dispatch action submit event', () => { - const { getByText } = renderWriteButtonsContainer(); + it('dispatch action submit event', () => { + const { getByText } = renderWriteButtonsContainer(); - fireEvent.click(getByText('등록하기')); + fireEvent.click(getByText('등록하기')); - expect(mockPush).not.toBeCalled(); + expect(mockPush).not.toBeCalled(); + }); }); }); - }); - context('with input value null, so validation check failure', () => { - describe('When the title and applyEndDate, personnel are blank', () => { - given('writeField', () => ({ - title: '', - contents: '우리는 이것저것 합니다.1', - moderatorId: 'user1', - applyEndDate: '', - participants: [], - personnel: '', - tags: [ - 'JavaScript', - 'Algorithm', - ], - })); - - it('renders error message "There are some items that have not been entered."', () => { - const { container, getByText } = renderWriteButtonsContainer(); - - fireEvent.click(getByText('등록하기')); - - expect(container).toHaveTextContent('입력이 안된 사항이 있습니다.'); + + context('with input value null, so validation check failure', () => { + describe('When the title and applyEndDate, personnel are blank', () => { + given('writeField', () => ({ + title: '', + contents: '우리는 이것저것 합니다.1', + moderatorId: 'user1', + applyEndDate: '', + participants: [], + personnel: '', + tags: [ + 'JavaScript', + 'Algorithm', + ], + })); + + it('renders error message "There are some items that have not been entered."', () => { + const { container, getByText } = renderWriteButtonsContainer(); + + fireEvent.click(getByText('등록하기')); + + expect(container).toHaveTextContent('입력이 안된 사항이 있습니다.'); + }); }); - }); - describe('When the length of tags is 0', () => { - given('writeField', () => ({ - title: '123', - contents: '우리는 이것저것 합니다.1', - moderatorId: 'user1', - applyEndDate: new Date().toString(), - participants: [], - personnel: '1', - tags: [], - })); + describe('When the length of tags is 0', () => { + given('writeField', () => ({ + title: '123', + contents: '우리는 이것저것 합니다.1', + moderatorId: 'user1', + applyEndDate: new Date().toString(), + participants: [], + personnel: '1', + tags: [], + })); - it('renders error message "Please enter a tag."', () => { - const { container, getByText } = renderWriteButtonsContainer(); + it('renders error message "Please enter a tag."', () => { + const { container, getByText } = renderWriteButtonsContainer(); - fireEvent.click(getByText('등록하기')); + fireEvent.click(getByText('등록하기')); - expect(container).toHaveTextContent('태그를 입력하세요.'); + expect(container).toHaveTextContent('태그를 입력하세요.'); + }); }); - }); - describe('When the application deadline is earlier than the current time', () => { - given('writeField', () => ({ - title: '123', - contents: '우리는 이것저것 합니다.1', - moderatorId: 'user1', - applyEndDate: '2020-10-01', - participants: [], - personnel: '1', - tags: [ - 'javascript', - 'react', - ], - })); - - it('renders error message "The application deadline is earlier than the current time."', () => { - const { container, getByText } = renderWriteButtonsContainer(); - - fireEvent.click(getByText('등록하기')); - - expect(container).toHaveTextContent('접수 마감날짜가 현재 시간보다 빠릅니다.'); + describe('When the application deadline is earlier than the current time', () => { + given('writeField', () => ({ + title: '123', + contents: '우리는 이것저것 합니다.1', + moderatorId: 'user1', + applyEndDate: '2020-10-01', + participants: [], + personnel: '1', + tags: [ + 'javascript', + 'react', + ], + })); + + it('renders error message "The application deadline is earlier than the current time."', () => { + const { container, getByText } = renderWriteButtonsContainer(); + + fireEvent.click(getByText('등록하기')); + + expect(container).toHaveTextContent('접수 마감날짜가 현재 시간보다 빠릅니다.'); + }); }); }); }); + + context('without user', () => { + given('user', () => (null)); + + given('writeField', () => ({ + title: '123', + contents: '우리는 이것저것 합니다.1', + moderatorId: 'user1', + applyEndDate: '2020-10-01', + participants: [], + personnel: '1', + tags: [ + 'javascript', + 'react', + ], + })); + + it('renders error message "Please use after logging in"', () => { + const { container, getByText } = renderWriteButtonsContainer(); + + fireEvent.click(getByText('등록하기')); + + expect(container).toHaveTextContent('로그인 후 이용하세요.'); + }); + }); }); }); diff --git a/src/pages/MainPage.jsx b/src/pages/MainPage.jsx index 3eaddee..8fa08b8 100644 --- a/src/pages/MainPage.jsx +++ b/src/pages/MainPage.jsx @@ -1,45 +1,13 @@ import React from 'react'; -import { Link } from 'react-router-dom'; - -import styled from '@emotion/styled'; - -import StudyGroupsContainer from '../containers/groups/StudyGroupsContainer'; import Responsive from '../styles/Responsive'; -import palette from '../styles/palette'; -const MainPageWrapper = styled(Responsive)` - -`; - -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]}; - } - } -`; +import StudyGroupsContainer from '../containers/groups/StudyGroupsContainer'; const MainPage = () => ( - - -

지금 바로 시작하세요!

- 스터디 개설하기 -
+ -
+ ); export default MainPage; diff --git a/src/pages/MainPage.test.jsx b/src/pages/MainPage.test.jsx index d647d86..0c1c9e1 100644 --- a/src/pages/MainPage.test.jsx +++ b/src/pages/MainPage.test.jsx @@ -19,6 +19,7 @@ describe('MainPage', () => { useSelector.mockImplementation((selector) => selector({ groups: STUDY_GROUPS, + user: given.user, })); }); @@ -35,12 +36,6 @@ describe('MainPage', () => { expect(container).toHaveTextContent('지금 바로 시작하세요!'); }); - it('renders Main Page Link text', () => { - const { container } = renderMainPage(); - - expect(container).toHaveTextContent('스터디 개설하기'); - }); - it('renders Main Page study group tags', () => { const { container } = renderMainPage(); @@ -50,6 +45,24 @@ describe('MainPage', () => { }); }); }); + + context('without user', () => { + given('user', () => (null)); + it("doesn't renders Main Page Link text", () => { + const { container } = renderMainPage(); + + expect(container).not.toHaveTextContent('스터디 개설하기'); + }); + }); + + context('with user', () => { + given('user', () => ('user')); + it('renders Main Page Link text', () => { + const { container } = renderMainPage(); + + expect(container).toHaveTextContent('스터디 개설하기'); + }); + }); }); it('calls dispatch with loadStudyGroups action', () => { diff --git a/src/reducers/slice.js b/src/reducers/slice.js index 4eada5f..68e6154 100644 --- a/src/reducers/slice.js +++ b/src/reducers/slice.js @@ -184,14 +184,12 @@ export const loadStudyGroup = (id) => async (dispatch) => { }; export const writeStudyGroup = () => async (dispatch, getState) => { - const { writeField } = getState(); + const { writeField, user } = getState(); - // NOTE: 현재 로그인 기능이 없는 관계로 임의로 작성자(moderatorId)와 참여자 목록(participants)에 넣어줌 - const groupId = await postStudyGroup({ - ...writeField, - moderatorId: 'user1', - participants: [...writeField.participants, 'user1'], - }); + const groupId = await postStudyGroup(produce(writeField, (draft) => { + draft.moderatorId = user; + draft.participants.push(user); + })); dispatch(successWrite(groupId)); dispatch(clearWriteFields()); @@ -204,7 +202,6 @@ export const updateStudyGroup = () => async (dispatch, getState) => { draft.participants.push(user); }); - // TODO: 같은 유저가 들어가도 update 된다. validation 하기 await updateParticipants(newGroup); dispatch(setStudyGroup(newGroup)); diff --git a/src/util/messages.js b/src/util/messages.js index d6e6eb0..cf5f7f6 100644 --- a/src/util/messages.js +++ b/src/util/messages.js @@ -5,6 +5,7 @@ export const ERROR_MESSAGE = { FAST_APPLY_DEADLINE: '접수 마감날짜가 현재 시간보다 빠릅니다.', FAILURE_REGISTER: '회원가입에 실패하였습니다.', FAILURE_LOGIN: '로그인에 실패하였습니다.', + NO_LOGGED_IN: '로그인 후 이용하세요.', }; export const FIREBASE_AUTH_ERROR_MESSAGE = {