diff --git a/fake-server/db.json b/fake-server/db.json index e88ad8c..38d45b9 100644 --- a/fake-server/db.json +++ b/fake-server/db.json @@ -4,7 +4,7 @@ "id": 0, "title": "스터디를 소개합니다.1", "moderatorId": "user1", - "applyEndDate": "2020-11-20 23:04", + "applyEndDate": "2020-11-22 17:36", "participants": [ "user1", "user2", @@ -40,7 +40,7 @@ "id": 2, "title": "스터디를 소개합니다.3", "moderatorId": "user3", - "applyEndDate": "2020-12-20", + "applyEndDate": "2020-11-22 18:08", "participants": [ "user1", "user2", diff --git a/src/components/common/DateTimeChange.jsx b/src/components/common/DateTimeChange.jsx new file mode 100644 index 0000000..4ae874f --- /dev/null +++ b/src/components/common/DateTimeChange.jsx @@ -0,0 +1,80 @@ +import React, { useState } from 'react'; + +import styled from '@emotion/styled'; + +import 'moment/locale/ko'; +import moment from 'moment'; +import Moment from 'react-moment'; + +import useInterval from '../../util/useInterval'; + +import DateTimeStatus from '../../styles/DateTimeStatus'; + +moment.locale('ko'); + +const DateTimeChangeWrapper = styled.div` + margin-top: .2rem; +`; + +const isCheckedTimeStatus = ({ + realTime, applyEndTime, participants, personnel, +}) => (!!((realTime - applyEndTime >= 0 || participants.length === personnel))); + +const DateTimeChange = ({ group, page }) => { + const { participants, personnel, applyEndDate } = group; + const applyEndTime = new Date(applyEndDate).getTime(); + + const [realTime, setRealTime] = useState(Date.now()); + + useInterval(() => { + setRealTime(Date.now()); + }, 1000); + + const valid = { + realTime, applyEndTime, participants, personnel, + }; + + const mainTimeStatus = () => { + if (isCheckedTimeStatus(valid)) { + return ( + 모집마감 + ); + } + + return ( + 모집중 + ); + }; + + const introduceTimeStatus = () => { + if (isCheckedTimeStatus(valid)) { + return ( + + 모집마감 + + ); + } + + return ( + + {applyEndTime} +  모집 마감 + + ); + }; + + return ( + + {page === 'introduce' + ? introduceTimeStatus() + : ( + <> + {`모집 인원: ${participants.length} / ${personnel}`} + {mainTimeStatus()} + + )} + + ); +}; + +export default DateTimeChange; diff --git a/src/components/common/DateTimeChange.test.jsx b/src/components/common/DateTimeChange.test.jsx new file mode 100644 index 0000000..0d08ff0 --- /dev/null +++ b/src/components/common/DateTimeChange.test.jsx @@ -0,0 +1,154 @@ +import React from 'react'; + +import { render } from '@testing-library/react'; + +import DateTimeChange from './DateTimeChange'; + +describe('DateTimeChange', () => { + const renderDateTimeChange = ({ group, page }) => render(( + + )); + + context('When on the main page', () => { + const page = 'main'; + + it('renders Recruitment number text', () => { + const group = { + applyEndDate: null, + participants: [ + 'user2', + ], + personnel: 2, + }; + + const { participants, personnel } = group; + + const { container } = renderDateTimeChange({ group, page }); + + expect(container).toHaveTextContent(`모집 인원: ${participants.length} / ${personnel}`); + }); + + describe('current time is before the application deadline', () => { + it('renders Recruiting text', () => { + const nowDate = new Date(); + const tomorrow = nowDate.setDate(nowDate.getDate() + 1); + + const group = { + applyEndDate: tomorrow, + participants: [ + 'user2', + ], + personnel: 2, + }; + + const { container } = renderDateTimeChange({ group, page }); + + expect(container).toHaveTextContent('모집중'); + }); + }); + + describe('current time is after the application deadline', () => { + it('renders Application deadline text', () => { + const nowDate = new Date(); + const yesterday = nowDate.setDate(nowDate.getDate() - 1); + + const group = { + applyEndDate: yesterday, + participants: [ + 'user2', + ], + personnel: 2, + }; + + const { container } = renderDateTimeChange({ group, page }); + + expect(container).toHaveTextContent('모집마감'); + }); + }); + + describe('When the number of study group participants equals the maximum number of participants', () => { + it('renders Application deadline text', () => { + const nowDate = new Date(); + const tomorrow = nowDate.setDate(nowDate.getDate() - 1); + + const group = { + applyEndDate: tomorrow, + participants: [ + 'user2', + 'user3', + ], + personnel: 2, + }; + + const { container } = renderDateTimeChange({ group, page }); + + expect(container).toHaveTextContent('모집마감'); + }); + }); + }); + + context('When on the introduce page', () => { + const page = 'introduce'; + + describe('current time is before the application deadline', () => { + it('renders Application deadline one day later text', () => { + const nowDate = new Date(); + const tomorrow = nowDate.setDate(nowDate.getDate() + 1); + + const group = { + applyEndDate: tomorrow, + participants: [ + 'user2', + ], + personnel: 2, + }; + + const { container } = renderDateTimeChange({ group, page }); + + expect(container).toHaveTextContent('하루 후 모집 마감'); + }); + }); + + describe('current time is after the application deadline', () => { + it('renders Application deadline text', () => { + const nowDate = new Date(); + const yesterday = nowDate.setDate(nowDate.getDate() - 1); + + const group = { + applyEndDate: yesterday, + participants: [ + 'user2', + ], + personnel: 2, + }; + + const { container } = renderDateTimeChange({ group, page }); + + expect(container).toHaveTextContent('모집마감'); + }); + }); + + describe('When the number of study group participants equals the maximum number of participants', () => { + it('renders Application deadline text', () => { + const nowDate = new Date(); + const tomorrow = nowDate.setDate(nowDate.getDate() - 1); + + const group = { + applyEndDate: tomorrow, + participants: [ + 'user2', + 'user3', + ], + personnel: 2, + }; + + const { container } = renderDateTimeChange({ group, page }); + + expect(container).toHaveTextContent('모집마감'); + }); + }); + }); +}); diff --git a/src/components/introduce/StudyIntroduceForm.jsx b/src/components/introduce/StudyIntroduceForm.jsx index ea9f80c..c9e49ef 100644 --- a/src/components/introduce/StudyIntroduceForm.jsx +++ b/src/components/introduce/StudyIntroduceForm.jsx @@ -4,6 +4,7 @@ import styled from '@emotion/styled'; import Tags from '../common/Tags'; import palette from '../../styles/palette'; +import DateTimeChange from '../common/DateTimeChange'; const StudyIntroduceWrapper = styled.div` margin-top: 6em; @@ -33,6 +34,7 @@ const IntroduceHeaderWrapper = styled.div` border: none; background: ${palette.teal[5]}; color: white; + cursor: pointer; &:hover{ background: ${palette.teal[4]}; } @@ -41,6 +43,7 @@ const IntroduceHeaderWrapper = styled.div` const IntroduceReferenceWrapper = styled.div` display: flex; + justify-content: space-evenly; padding: 1rem; border-radius: 0.75rem; background-color: ${palette.gray[1]}; @@ -61,7 +64,6 @@ const ModeratorWrapper = styled.div` `; const IntroduceReference = styled.div` - padding-left: 50px; padding-right: 50px; border-right: 0.1rem solid ${palette.gray[3]}; `; @@ -89,6 +91,7 @@ const StudyIntroduceForm = ({ group }) => { const { title, contents, tags, moderatorId, personnel, participants, applyEndDate, } = group; + return ( @@ -106,9 +109,13 @@ const StudyIntroduceForm = ({ group }) => { - + {applyEndDate} + 소개 diff --git a/src/components/main/DateTimeChange.jsx b/src/components/main/DateTimeChange.jsx deleted file mode 100644 index 158ecb6..0000000 --- a/src/components/main/DateTimeChange.jsx +++ /dev/null @@ -1,49 +0,0 @@ -import React, { useState } from 'react'; - -import styled from '@emotion/styled'; - -import useInterval from '../../util/useInterval'; - -import DateTimeStatus from '../../styles/DateTimeStatus'; - -const DateTimeChangeWrapper = styled.div``; - -const isCheckedTimeStatus = ({ - realTime, applyEndTime, participants, personnel, -}) => (!!((realTime - applyEndTime >= 0 || participants.length === personnel))); - -const DateTimeChange = ({ group }) => { - const { participants, personnel, applyEndDate } = group; - const applyEndTime = new Date(applyEndDate).getTime(); - - const [realTime, setRealTime] = useState(Date.now()); - - useInterval(() => { - setRealTime(Date.now()); - }, 1000); - - const valid = { - realTime, applyEndTime, participants, personnel, - }; - - const timeStatusChange = () => { - if (isCheckedTimeStatus(valid)) { - return ( - 모집마감 - ); - } - - return ( - 모집중 - ); - }; - - return ( - - {`모집 인원: ${participants.length} / ${personnel}`} - {timeStatusChange()} - - ); -}; - -export default DateTimeChange; diff --git a/src/components/main/DateTimeChange.test.jsx b/src/components/main/DateTimeChange.test.jsx deleted file mode 100644 index 8181f8d..0000000 --- a/src/components/main/DateTimeChange.test.jsx +++ /dev/null @@ -1,71 +0,0 @@ -import React from 'react'; - -import { render } from '@testing-library/react'; - -import DateTimeChange from './DateTimeChange'; - -describe('DateTimeChange', () => { - const renderDateTimeChange = ({ group }) => render(( - - )); - - describe('current time is before the application deadline', () => { - it('renders Recruiting text', () => { - const nowDate = new Date(); - const tomorrow = nowDate.setDate(nowDate.getDate() + 1); - - const group = { - applyEndDate: tomorrow, - participants: [ - 'user2', - ], - personnel: 2, - }; - - const { container } = renderDateTimeChange({ group }); - - expect(container).toHaveTextContent('모집중'); - }); - }); - - describe('current time is after the application deadline', () => { - it('renders Application deadline text', () => { - const nowDate = new Date(); - const yesterday = nowDate.setDate(nowDate.getDate() - 1); - - const group = { - applyEndDate: yesterday, - participants: [ - 'user2', - ], - personnel: 2, - }; - - const { container } = renderDateTimeChange({ group }); - - expect(container).toHaveTextContent('모집마감'); - }); - }); - - describe('When the number of study group participants equals the maximum number of participants', () => { - it('renders Application deadline text', () => { - const nowDate = new Date(); - const tomorrow = nowDate.setDate(nowDate.getDate() - 1); - - const group = { - applyEndDate: tomorrow, - participants: [ - 'user2', - 'user3', - ], - personnel: 2, - }; - - const { container } = renderDateTimeChange({ group }); - - expect(container).toHaveTextContent('모집마감'); - }); - }); -}); diff --git a/src/components/main/StudyGroup.jsx b/src/components/main/StudyGroup.jsx index b9de983..13cdd57 100644 --- a/src/components/main/StudyGroup.jsx +++ b/src/components/main/StudyGroup.jsx @@ -8,7 +8,7 @@ import Moment from 'react-moment'; import Tags from '../common/Tags'; import palette from '../../styles/palette'; -import DateTimeChange from './DateTimeChange'; +import DateTimeChange from '../common/DateTimeChange'; const StudyGroupWrapper = styled.div` margin: 1em .5em 1em .5em; @@ -52,7 +52,10 @@ const StudyGroup = ({ group }) => {
{moderatorId}
- +
{'마감 일자: '} diff --git a/src/styles/DateTimeStatus.jsx b/src/styles/DateTimeStatus.jsx index b8e38a5..225a033 100644 --- a/src/styles/DateTimeStatus.jsx +++ b/src/styles/DateTimeStatus.jsx @@ -17,7 +17,7 @@ const DateTimeStatusWrapper = styled.div` margin-top: 1rem; margin-bottom: 1rem; - ${(props) => props.status === 'recruit' + ${(props) => props.status === 'mainRecruit' && css` background: ${palette.cyan[4]}; animation: blink-animation 1.5s steps(5, start) infinite; @@ -34,11 +34,42 @@ const DateTimeStatusWrapper = styled.div` } `} - - ${(props) => props.status === 'deadline' + ${(props) => props.status === 'mainDeadline' && css` background: #ff6b6b; `} + + ${(props) => props.status === 'introduceRecruit' + && css` + margin: 0 auto; + padding: .5rem 50px .5rem 50px; + background: white; + align-items: center; + color: ${palette.orange[4]}; + border: 1.5px solid ${palette.orange[4]}; + animation: blink-animation 1.5s steps(5, start) infinite; + -webkit-animation: blink-animation 1.5s steps(5, start) infinite; + @keyframes blink-animation { + to { + visibility: hidden; + } + } + @-webkit-keyframes blink-animation { + to { + visibility: hidden; + } + } + `} + + ${(props) => props.status === 'introduceDeadline' + && css` + margin: 0 auto; + padding: .5rem 50px .5rem 50px; + align-items: center; + background: white; + color: #ff6b6b; + border: 1.5px solid #ff6b6b; + `} `; const DateTimeStatus = ({ children, status }) => (