diff --git a/src/App.js b/src/App.js index 4395d60..f969340 100644 --- a/src/App.js +++ b/src/App.js @@ -10,6 +10,8 @@ import NavBar from './Components/NavBar/NavBar' import MainPage from './Pages/MainPage' import SideBar from './Components/SideBar/SideBar' import GroupMainPage from './Pages/GroupMainPage' +import ShowEventList from './Pages/ShowEventList' +import UploadMember from './Pages/UploadMember' const StyledLayout = styled.div` // background-color: gray; @@ -19,14 +21,14 @@ const StyledLayout = styled.div` ` function App() { - const group_id = "662a83742c217fe65efaeab6"; + const group_id = '662a83742c217fe65efaeab6' return (
- + } /> } /> @@ -34,6 +36,8 @@ function App() { } /> } /> } /> + } /> + } />
diff --git a/src/Components/Card/EventCard.js b/src/Components/Card/EventCard.js new file mode 100644 index 0000000..eb00987 --- /dev/null +++ b/src/Components/Card/EventCard.js @@ -0,0 +1,39 @@ +import React, { useState, useEffect } from 'react' +import { Collapse } from 'antd' +import { getEvent } from '../../apis/event' +import styled from 'styled-components' + +const { Panel } = Collapse + +const EventCard = ({ groupId }) => { + const [events, setEvents] = useState([]) + useEffect(() => { + getEvent(groupId).then((data) => { + setEvents(data) + }) + }, [groupId]) + + return ( + + {events.map((event) => ( + +

+ 설명: {event.description} +

+

+ 회비: {event.fee} +

+
+ ))} +
+ ) +} + +const StyledCollapse = styled(Collapse)` + width: 60%; + margin-top: 100px; + padding: 10px; + background-color: rgba(0, 62.67, 151.94, 0.08); +` + +export default EventCard diff --git a/src/Components/GroupCard/GroupCard.js b/src/Components/Card/GroupCard.js similarity index 94% rename from src/Components/GroupCard/GroupCard.js rename to src/Components/Card/GroupCard.js index f55b48c..382e928 100644 --- a/src/Components/GroupCard/GroupCard.js +++ b/src/Components/Card/GroupCard.js @@ -13,20 +13,20 @@ const StyledBox = styled.div` const StyledRow = styled(Row)` width: 100%; - margin: 10px; + margin: 0 10px 10px 10px; padding: 10px; ` const StyledCol = styled(Col)` width: 100%; - margin: 10px; + margin: 0 10px 10px 10px; padding: 10px; ` const StyledCard = styled(Card)` width: 100%; background-color: #f9fbff; - margin: 20px; + margin: 0 20px 20px 20px; transition-duration: 0.3s, 0.3s; border: 2px solid #f0f0f0; &:hover { diff --git a/src/Components/Forms/CreateForm.js b/src/Components/Forms/CreateForm.js index e3bf01b..f3bebae 100644 --- a/src/Components/Forms/CreateForm.js +++ b/src/Components/Forms/CreateForm.js @@ -78,6 +78,7 @@ export default CreateForm // 전체 폼을 감싸는 스타일드 컴포넌트 const StyledForm = styled(Form)` margin: 30px; + width: 100%; ` // 폼을 감싸는 스타일드 컴포넌트 const StyledFormWrapper = styled.div` @@ -116,5 +117,6 @@ const StyledFormItems = styled(Form.Item)` height: 50px; width: 100px; font-size: 24px; + margin: 5% 0 0 40%; } ` diff --git a/src/Components/Tables/Tables.js b/src/Components/Tables/Tables.js index 327b249..cec7832 100644 --- a/src/Components/Tables/Tables.js +++ b/src/Components/Tables/Tables.js @@ -4,8 +4,26 @@ import PropTypes from 'prop-types' import styled from 'styled-components' import AddMemberButton from '../Buttons/AddMemberButton' import DeleteMemberButton from '../Buttons/DeleteMemberButton' +//getGroupDetail로 변경 +import { getMember } from '../../apis/members' + +const Tables = ({ groupId }) => { + const [members, setMembers] = useState([]) + const [memberKeys, setMemberKeys] = useState([]) + + useEffect(() => { + getMember(groupId).then((data) => { + setMembers(data) + }) + }, [groupId]) + + useEffect(() => { + const keys = Object.keys(members[0]?.memberInfo || {}) + setMemberKeys(keys) + }, [members]) + + console.log(memberKeys) -const Tables = ({ members, groupId }) => { const columns = [ { title: '순', @@ -15,18 +33,10 @@ const Tables = ({ members, groupId }) => { title: '이름', dataIndex: 'name', }, - { - title: '학번', - dataIndex: 'studentId', - }, - { - title: '전화번호', - dataIndex: 'phoneNumber', - }, - { - title: '비고', - dataIndex: 'remark', - }, + ...memberKeys.map((key) => ({ + title: key, + dataIndex: key, + })), ] const data = [] @@ -36,9 +46,7 @@ const Tables = ({ members, groupId }) => { key: i, index: i + 1, name: members[i].name, - studentId: members[i].memberInfo.studentId, - phoneNumber: members[i].memberInfo.phoneNumber, - remark: members[i].memberInfo.remark, + ...members[i].memberInfo, }) } @@ -48,6 +56,7 @@ const Tables = ({ members, groupId }) => { useEffect(() => { const ids = selectedRows.map((row) => row._id) + setDeleteMemberIds(ids) }, [selectedRows]) @@ -110,17 +119,6 @@ const StyledTable = styled(Table)` } ` Tables.propTypes = { - members: PropTypes.arrayOf( - PropTypes.shape({ - _id: PropTypes.string.isRequired, - name: PropTypes.string.isRequired, - memberInfo: PropTypes.shape({ - studentId: PropTypes.string.isRequired, - phoneNumber: PropTypes.string.isRequired, - remark: PropTypes.string, - }), - }), - ).isRequired, groupId: PropTypes.string.isRequired, } export default Tables diff --git a/src/Components/Upload/UploadMember.js b/src/Components/Upload/UploadMember.js new file mode 100644 index 0000000..8a67129 --- /dev/null +++ b/src/Components/Upload/UploadMember.js @@ -0,0 +1,99 @@ +import React, { useState } from 'react' +import { uploadMember } from '../../apis/members' +import { InboxOutlined } from '@ant-design/icons' +import { Upload, Button } from 'antd' +import styled from 'styled-components' + +const { Dragger } = Upload + +const UploadMember = ({ groupId }) => { + const [file, setFile] = useState(null) + const [isFileUploaded, setIsFileUploaded] = useState(false) + + const props = { + name: 'file', + accept: '.xlsx, .xls, .csv', + multiple: false, + showUploadList: false, + beforeUpload: (file) => { + setFile(file) + setIsFileUploaded(true) + return false + }, + } + + const handleUpload = async () => { + await uploadMember(groupId, file).then((res) => { + console.log(res) + }) + alert('파일이 업로드되었습니다.') + window.location.reload() + } + + return ( + + + 확인 + + + + {file ? ( + + file +

{file.name}

+
+ ) : ( +
+

+ +

+

클릭 또는 파일을 드래그하여 업로드하세요

+

xlsx, csv 파일만 첨부 가능

+
+ )} +
+
+ ) +} + +export const StyledButton = styled(Button)` + margin-top: 20px; + margin-bottom: 10px; + width: 100px; + height: 50px; + font-size: 20px; + font-weight: 500; + + //글씨 수직 맞추기 + display: flex; + justify-content: center; + align-items: center; + background-color: #003e97; +` +export const StyledDragger = styled(Dragger)` + width: 100%; + height: 100%; + padding: 10px; + background-color: rgba(0, 62.67, 151.94, 0.08); + border-radius: 10px; +` + +export const Wrapper = styled.div` + display: flex; + flex-direction: column; + align-items: end; + width: 50%; +` +const FileIconWrapper = styled.div` + width: 100%; + height: 100%; + display: flex; + justify-content: center; + align-items: center; +` + +export default UploadMember diff --git a/src/Pages/CreateGroupPage/index.js b/src/Pages/CreateGroupPage/index.js index 36ba16b..388909f 100644 --- a/src/Pages/CreateGroupPage/index.js +++ b/src/Pages/CreateGroupPage/index.js @@ -1,12 +1,15 @@ import React from 'react' import CreateForm from '../../Components/Forms/CreateForm' //import CreateForm from '../../Components/Forms/CreateForm' - +import styled from 'styled-components' +const StyledBack = styled.div` + width: 100%; +` const CreateGroup = () => { return ( -
+ -
+ ) } diff --git a/src/Pages/MainPage/index.js b/src/Pages/MainPage/index.js index 6af1014..6993cc9 100644 --- a/src/Pages/MainPage/index.js +++ b/src/Pages/MainPage/index.js @@ -9,12 +9,14 @@ const MainPage = () => { navigate('/group') } + return (
환영합니다... 로그인하기...

+
) } diff --git a/src/Pages/ShowEventList/index.js b/src/Pages/ShowEventList/index.js new file mode 100644 index 0000000..117dab7 --- /dev/null +++ b/src/Pages/ShowEventList/index.js @@ -0,0 +1,10 @@ +import React from 'react' +import EventCard from '../../Components/Card/EventCard' + +const ShowEventList = () => { + const groupId = window.location.href.split('/')[4] + + return +} + +export default ShowEventList diff --git a/src/Pages/ShowGroupDetails/index.js b/src/Pages/ShowGroupDetails/index.js index ea8e852..05696d4 100644 --- a/src/Pages/ShowGroupDetails/index.js +++ b/src/Pages/ShowGroupDetails/index.js @@ -1,6 +1,5 @@ -import React, { useEffect, useState } from 'react' +import React from 'react' import styled from 'styled-components' -import { getMember } from '../../apis/members' import Tables from '../../Components/Tables/Tables' const Wrapper = styled.div` @@ -12,18 +11,12 @@ const Wrapper = styled.div` ` const ShowGroupDetails = () => { - const [members, setMembers] = useState([]) const groupId = window.location.href.split('/')[4] - useEffect(() => { - getMember(groupId).then((data) => { - setMembers(data) - }) - }, [groupId]) return (
- +
) diff --git a/src/Pages/ShowGroupList/index.js b/src/Pages/ShowGroupList/index.js index cc93fd2..eb8e681 100644 --- a/src/Pages/ShowGroupList/index.js +++ b/src/Pages/ShowGroupList/index.js @@ -1,19 +1,44 @@ import React from 'react' -import GroupCard from '../../Components/GroupCard/GroupCard' +import GroupCard from '../../Components/Card/GroupCard' import styled from 'styled-components' +import { useNavigate } from 'react-router-dom' +import { Button } from 'antd' const StyledGroupListLayout = styled.div` display: flex; flex-direction: column; width: 100%; ` + +const StyledGroupPageLayout = styled.div` + display: flex; + flex-direction: column; + width: 100%; +` + +const StyledButtonSection = styled.div` + display: flex; + padding: 5px 80%; +` + const ShowGroupList = () => { - - return ( + const navigate = useNavigate() + const onClickCreateGroup = () => { + navigate('/createGroup') + } + return ( + + + + + - ) + + ) } export default ShowGroupList diff --git a/src/Pages/UploadMember/index.js b/src/Pages/UploadMember/index.js new file mode 100644 index 0000000..3eea758 --- /dev/null +++ b/src/Pages/UploadMember/index.js @@ -0,0 +1,9 @@ +import React from 'react' +import UploadMember from '../../Components/Upload/UploadMember' + +const UploadMembers = () => { + const groupId = window.location.href.split('/')[4] + return +} + +export default UploadMembers diff --git a/src/apis/groups.js b/src/apis/groups.js index e2e3745..f776bc0 100644 --- a/src/apis/groups.js +++ b/src/apis/groups.js @@ -6,7 +6,13 @@ export const getGroups = async () => { return response.data } +export const getGroupDetail = async (groupId) => { + const response = await api.get(`/group/${groupId}`) + return response.data +} + export const createGroup = async (groupInfo) => { + console.log(groupInfo) const response = await formApi.post('/group', groupInfo) return response.data } diff --git a/src/apis/index.js b/src/apis/index.js index 2566b55..c29d0c6 100644 --- a/src/apis/index.js +++ b/src/apis/index.js @@ -14,4 +14,38 @@ export const formApi = axios.create({ }, }) +// api.interceptors.request.use( +// (config) => { +// console.log(config) +// return config +// }, +// function (error) { +// console.log('request error', error) +// return Promise.reject(error) +// }, +// ) + +// api.interceptors.response.use( +// function (response) { +// console.log('get response', response) +// return response +// }, +// async (error) => { +// const { +// config, +// response: { status }, +// } = error +// if (status === 401) { +// if (error.response.data.message === 'expired') { +// const originalRequest = config +// const refreshToken = await localStorage.getItem('refreshToken') +// const { data } = await axios.post( +// `http:://localhost:3000/refreshToken`, +// {}, +// { headers: { Authorization: `Bearer ${refreshToken}` } }, +// ) +// } +// } +// }, +// ) export default api diff --git a/src/apis/members.js b/src/apis/members.js index 7a9b0ad..591a79c 100644 --- a/src/apis/members.js +++ b/src/apis/members.js @@ -1,4 +1,5 @@ import api from './index' +import { formApi } from './index' export const getMember = async (groupId) => { try { @@ -10,14 +11,27 @@ export const getMember = async (groupId) => { } export const addMember = async (groupId, name, memberInfo) => { - const response = await api.post(`group/${groupId}/member`, { - name, - memberInfo, - }) + console.log(name, memberInfo) + const response = await api.post(`group/${groupId}/member`, [ + { + name, + memberInfo, + }, + ]) return response.data } export const deleteMember = async (groupId, memberId) => { - const response = await api.delete(`group/${groupId}/member/${memberId}`) + const response = await api.delete(`group/${groupId}/member`, memberId) + return response.data +} + +export const uploadMember = async (groupId, file) => { + console.log(groupId) + console.log(file) + + const formData = new FormData() + formData.append('memberFile', file) + const response = await formApi.post(`group/${groupId}/member/excel`, formData) return response.data }