Skip to content

Commit

Permalink
feat: 질문리스트 기능추가 (#66)
Browse files Browse the repository at this point in the history
TODO
 - redux dispatch 비동기작업
 - input bar conflict잡기
 - 질문 리스트 삭제
 - 질문 삭제
 - 이동 관련 순서 저장하기
  • Loading branch information
SkynI25 authored and Lavegaa committed Dec 2, 2020
1 parent f4cb2e3 commit 36cc98b
Show file tree
Hide file tree
Showing 20 changed files with 391 additions and 98 deletions.
5 changes: 4 additions & 1 deletion src/components/Icon/Icon.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ background-position: ${({ type }) => (type === 'bubble_white' ? '-44px -36px'
`;

export default function Icon({
type, alt, style, src,
type, alt, style, src, func,
}) {
const [size, setSize] = useState('md');
useEffect(() => {
Expand Down Expand Up @@ -146,12 +146,14 @@ export default function Icon({
src={src}
alt={alt}
style={style}
onClick={func}
/>
) : (
<I
type={type}
size={size}
title={alt}
onClick={func}
/>
);
}
Expand Down Expand Up @@ -220,6 +222,7 @@ Icon.propTypes = {
alt: PropTypes.string.isRequired,
src: PropTypes.string,
style: PropTypes.string,
func: PropTypes.func,
};
Icon.defaultProp = {
type: 'test',
Expand Down
4 changes: 2 additions & 2 deletions src/components/InputBar/InputBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ const Wrapper = styled.input`
`;

export default function InputBar({
className,
className, placeholder, value, onchange,
}) {
return (
<Wrapper className={className} type="text" placeholder="기업명을 입력해주세요" />
<Wrapper className={className} type="text" placeholder={placeholder} value={value} onChange={onchange} />
);
}

Expand Down
10 changes: 9 additions & 1 deletion src/components/Modal/Modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,25 @@ import { useSelector } from 'react-redux';
import PropTypes from 'prop-types';
import QuestionListSaveModal from './QuestionListSaveModal';
import { MODALS } from '../../utils/constant';
import SelfTrainStartModal from './SelfTrainStartModal';
import ModalWrapper from './ModalWrapper';

export default function Modal({
modalName,
}) {
const isShow = useSelector((state) => state.modal[modalName]);
const modalList = {
[MODALS.QUESTIONLIST_SAVE_MODAL]: <QuestionListSaveModal />,
[MODALS.SELF_TRAIN_START_MODAL]: <SelfTrainStartModal />,
};
return (
<>
{ isShow && modalList[modalName] }
{ isShow
&& (
<ModalWrapper modalName={modalName}>
{modalList[modalName]}
</ModalWrapper>
)}
</>
);
}
Expand Down
56 changes: 56 additions & 0 deletions src/components/Modal/Modal.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/* eslint-disable react/jsx-props-no-spreading */
import React from 'react';
import { Provider } from 'react-redux';
import { configureStore, combineReducers, createSlice } from '@reduxjs/toolkit';
import Modal from './Modal';
import { MODALS } from '../../utils/constant';

const modalReducer = createSlice({
name: 'modal',
initialState: {
[MODALS.QUESTIONLIST_SAVE_MODAL]: true,
[MODALS.SELF_TRAIN_START_MODAL]: true,
},
reducers: {
displayModal(state, { payload: { modalName } }) {
return {
...state,
[modalName]: true,
};
},
removeModal(state, { payload: { modalName } }) {
return {
...state,
[modalName]: false,
};
},
},
});

const reducers = combineReducers({
modal: modalReducer.reducer,
});

const store = configureStore({ reducer: reducers });

const withReduxMockStore = (story) => (
<Provider store={store}>{story()}</Provider>
);

export default {
title: 'Modal',
description: 'modals',
decorators: [withReduxMockStore],
};

const modals = (args) => <Modal {...args} />;
export const QuestionListSaveModal = modals.bind({});
export const SelfTrainStartModal = modals.bind({});

QuestionListSaveModal.args = {
modalName: MODALS.QUESTIONLIST_SAVE_MODAL,
};

SelfTrainStartModal.args = {
modalName: MODALS.SELF_TRAIN_START_MODAL,
};
68 changes: 68 additions & 0 deletions src/components/Modal/ModalWrapper/ModalWrapper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import React from 'react';
import styled from 'styled-components';
import PropTypes from 'prop-types';
import { useDispatch } from 'react-redux';
import { hideModal } from '../../../store/Modal/modal';

const Background = styled.div`
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0,0,0,0.4);
z-index: 999;
`;

const Wrapper = styled.div`
display: flex;
justify-content: center;
align-items: center;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
overflow: auto;
outline: none;
z-index: 1000;
`;

const Content = styled.div`
display: inline-block;
border-radius: 10px;
box-shadow: 0 6px 12px 0 rgba(4, 4, 161, 0.04);
background-color: #ffffff;
margin: 0 auto;
outline: none;
`;

export default function ModalWrapper({ modalName, children }) {
const dispatch = useDispatch();
const handleCloseModal = (e) => {
if (e.target === e.currentTarget) {
dispatch(hideModal(modalName));
}
};

return (
<>
<Background />
<Wrapper tabIndex="-1" onClick={handleCloseModal}>
<Content tabIndex="0">
{children}
</Content>
</Wrapper>
</>
);
}

ModalWrapper.propTypes = {
modalName: PropTypes.string,
children: PropTypes.element,
};

ModalWrapper.defaultProp = {
modalName: '',
};
1 change: 1 addition & 0 deletions src/components/Modal/ModalWrapper/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './ModalWrapper';
125 changes: 53 additions & 72 deletions src/components/Modal/QuestionListSaveModal/QuestionListSaveModal.js
Original file line number Diff line number Diff line change
@@ -1,49 +1,19 @@
import React from 'react';
import React, { useState } from 'react';
import styled from 'styled-components';
import { useDispatch } from 'react-redux';
import { hideModal } from '../../../store/Modal/modal';
import { useDispatch, useSelector } from 'react-redux';
import { hideModal, showModal } from '../../../store/Modal/modal';
import InputBar from '../../InputBar';
import Button from '../../Button';

const Background = styled.div`
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0,0,0,0.4);
z-index: 1;
`;
import { postQuestionListAPI, postQuestionItemAPI } from '../../../repository/questionListRepository';
import { get } from '../../../utils/snippet';
import { MODALS } from '../../../utils/constant';

const Wrapper = styled.div`
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
overflow: auto;
outline: none;
z-index: 2;
`;

const Content = styled.div`
position: relative;
top: 50%;
transform: translateY(-50%);
width: 660px;
height: 876px;
border-radius: 10px;
box-shadow: 0 6px 12px 0 rgba(4, 4, 161, 0.04);
background-color: #ffffff;
margin: 0 auto;
outline: none;
`;

const ModalWrapper = styled.div`
display: flex;
flex-direction: column;
align-items: center;
width: 660px;
height: 876px;
`;

const Text = styled.div`
Expand Down Expand Up @@ -81,43 +51,54 @@ const ButtonWrapper = styled.div`

const QuestionListSaveModal = () => {
const dispatch = useDispatch();
const handleCloseModal = (e) => {
if (e.target === e.currentTarget) {
dispatch(hideModal('questionListSaveModal'));
}
const qeustionSelector = useSelector(get('question'));
const [title, setTitle] = useState();
const [enterprise, setEnterprise] = useState();
const [job, setJob] = useState();

const handleListMake = () => {
postQuestionListAPI({ title, enterprise, job }).then((response) => {
postQuestionItemAPI({
listId: response.data.id,
questions: qeustionSelector.questions,
}).then(() => {
dispatch(hideModal(MODALS.QUESTIONLIST_SAVE_MODAL));
dispatch(showModal(MODALS.SELF_TRAIN_START_MODAL));
});
});
};

const handleInputChange = (e, setState) => {
setState(e.target.value);
};

return (
<>
<Background />
<Wrapper tabIndex="-1" onClick={handleCloseModal}>
<Content tabIndex="0">
<ModalWrapper>
<Text>
질문 리스트 저장
</Text>
<InputWrapper>
<InputText>
질문 리스트 제목
</InputText>
<InputBar />
</InputWrapper>
<InputWrapper>
<InputText>
기업 이름
</InputText>
<InputBar />
</InputWrapper>
<InputWrapper>
<InputText>
직무 이름
</InputText>
<InputBar />
</InputWrapper>
<ButtonWrapper>
<Button text="확인" theme="blue" />
</ButtonWrapper>
</ModalWrapper>
</Content>
<Wrapper>
<Text>
질문 리스트 저장
</Text>
<InputWrapper>
<InputText>
질문 리스트 제목
</InputText>
<InputBar placeholder="제목을 입력해주세요." value={title} onchange={(e) => handleInputChange(e, setTitle)} />
</InputWrapper>
<InputWrapper>
<InputText>
기업 이름
</InputText>
<InputBar placeholder="기업명을 입력해주세요." value={enterprise} onchange={(e) => handleInputChange(e, setEnterprise)} />
</InputWrapper>
<InputWrapper>
<InputText>
직무 이름
</InputText>
<InputBar placeholder="직무명을 입력해주세요." value={job} onchange={(e) => handleInputChange(e, setJob)} />
</InputWrapper>
<ButtonWrapper onClick={handleListMake}>
<Button text="저장" theme="blue" />
</ButtonWrapper>
</Wrapper>
</>
);
Expand Down
Loading

0 comments on commit 36cc98b

Please sign in to comment.