diff --git a/src/api.jsx b/src/api.jsx index cc1031c..025f5f1 100644 --- a/src/api.jsx +++ b/src/api.jsx @@ -181,11 +181,28 @@ export const addUserInOrganization = async (organizationName, userInfo) => { alert("organization에 사용자가 추가되었습니다"); } } catch (error) { - console.log(error); + if (error.response.data.status === 409) { + alert("해당 사용자는 이미 그룹에 있습니다."); + } throw new Error("Add user in organization error"); } }; +// organization에서 사용자 삭제 +export const deleteOrganizationMember = async (organizationName, username) => { + try { + const response = await axios.delete( + `${SERVER}/api/v1/organization/${organizationName}/${username}` + ); + if (response.status === 200) { + alert("해당 사용자가 그룹에서 제외되었습니다"); + } + } catch (error) { + console.log(error); + throw new Error("delete organization error"); + } +}; + // 사용자별 organization 목록 조회 export const getAllOrganization = async (username) => { try { @@ -200,10 +217,42 @@ export const getAllOrganization = async (username) => { }; export const useGetAllOrganizations = (username) => { - return useQuery(["organizations"], () => getAllOrganization(username), { - staleTime: 5000, - cacheTime: Infinity, - }); + return useQuery( + ["organizationList", username], + () => getAllOrganization(username), + { + staleTime: 5000, + cacheTime: Infinity, + } + ); +}; + +// 그룹의 사용자 목록 조회 +export const getOrganizationMemberList = async (organizationName) => { + try { + const { data } = await axios.get( + `${SERVER}/api/v1/organization/${organizationName}`, + {} + ); + return data; + } catch (err) { + throw new Error("fetch all organization error"); + } +}; + +export const useGetOrganizationMemberList = (organizationName) => { + return useQuery( + ["memberList", organizationName], + () => getOrganizationMemberList(organizationName), + { + enabled: false, + staleTime: 5000, + cacheTime: Infinity, + refetchOnWindowFocus: false, + initialData: [], + } + ); + }; //////////////////////공유 파일///////////////////////// @@ -267,6 +316,7 @@ export const deleteSharedFile = async (organizationName, fileName) => { } }; + // 파일로 실행 export const runFile = async (userInfo) => { try { @@ -361,3 +411,4 @@ export const getAllResource = async () => { } }; + diff --git a/src/atom.jsx b/src/atom.jsx index fbd43ac..7ef9724 100644 --- a/src/atom.jsx +++ b/src/atom.jsx @@ -1,8 +1,8 @@ import { atom } from "recoil"; -export const loginState = atom({ key: "login", default: true }); +export const loginState = atom({ key: "login", default: false }); -export const adminState = atom({ key: "admin", default: false }); +export const adminState = atom({ key: "admin", default: true }); export const adminCategoryModalVisibleState = atom({ key: "adminCategoryModal", diff --git a/src/components/atoms/button.jsx b/src/components/atoms/button.jsx index 009ae2d..371b658 100644 --- a/src/components/atoms/button.jsx +++ b/src/components/atoms/button.jsx @@ -13,6 +13,8 @@ const CustomButton = styled.button` background-color: ${(props) => props.bgColor}; font-size: ${(props) => `${props.fontSize}rem`}; font-weight: ${(props) => props.fontWeight}; + //border: ${(props) => props.border}; + margin-top: ${(props) => `${props.marginTop}rem`}; ${(props) => props.hoverEvent && css` @@ -37,6 +39,7 @@ const Button = ({ fontWeight = 700, border = "none", hoverEvent = false, + marginTop = "0", borderBottom, }) => { return ( @@ -52,6 +55,7 @@ const Button = ({ fontWeight={fontWeight} border={border} hoverEvent={hoverEvent} + marginTop={marginTop} borderBottom={borderBottom} type="button" > diff --git a/src/components/atoms/text.jsx b/src/components/atoms/text.jsx index c4ad882..ec397ff 100644 --- a/src/components/atoms/text.jsx +++ b/src/components/atoms/text.jsx @@ -6,6 +6,7 @@ const Text = ({ fontWeight = "normal", color = "black", marginTop = "0vh", + marginRight = "0vh", marginBottom = "0vh", marginLeft = "0vh", onClick, @@ -33,6 +34,7 @@ const Text = ({ marginBottom: marginBottom, marginLeft: marginLeft, fontFamily: "inter", + marginRight: marginRight, }} > {children} diff --git a/src/components/molecules/flexColumn.jsx b/src/components/molecules/flexColumn.jsx index fe88ccf..f4ab75e 100644 --- a/src/components/molecules/flexColumn.jsx +++ b/src/components/molecules/flexColumn.jsx @@ -14,7 +14,7 @@ const Container = styled.div` padding-left: ${(props) => `${props.horizontalPadding}rem`}; padding-right: ${(props) => `${props.horizontalPadding}rem`}; align-content: center; - //align-items: center; + // align-items: center; text-align: center; vertical-align: middle; `; diff --git a/src/components/pages/organization.jsx b/src/components/pages/organization.jsx new file mode 100644 index 0000000..5cc8ce5 --- /dev/null +++ b/src/components/pages/organization.jsx @@ -0,0 +1,330 @@ +import React, { Fragment, useEffect, useState } from "react"; +import Body from "../atoms/body"; +import styled from "styled-components"; +import { + addOrganization, + addUserInOrganization, + deleteOrganizationMember, + useGetAllOrganizations, + useGetOrganizationMemberList, +} from "../../api"; +import Button from "../atoms/button"; +import Input from "../atoms/input"; +import Text from "../atoms/text"; +import { BiArrowFromLeft } from "react-icons/bi"; +import { useRecoilValue } from "recoil"; +import { adminState } from "../../atom"; + +// 레이아웃 + +const SideMenu = styled.div` + position: fixed; + left: 0; + width: 4rem; + height: 100%; + background: lightgray; +`; +const Content = styled.div` + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + justify-content: center; + vertical-align: middle; +`; + +const AdminContent = styled.div` + width: 100%; + position: fix; + height: 10rem; + display: flex; + flex-direction: row; + justify-content: space-evenly; + padding-left: 4rem; + padding-top: 3rem; +`; + +const OrganizationContent = styled.div` + width: 100%; + height: 30.5rem; + display: flex; + flex-direction: row; + padding-left: 4rem; + padding-top: 2rem; +`; + +// AdminContent + +const CreateGroup = styled.div` + width: 25rem; + height: 10rem; + display: flex; + flex-direction: row; + justify-content: space-evenly; + vertical-align: middle; +`; + +const InsertUser = styled.div` + width: 25rem; + height: 10rem; + display: flex; + flex-direction: row; + justify-content: space-evenly; + vertical-align: middle; +`; + +// OrganizationContent + +const LeftContent = styled.div` + width: 726px; + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +`; + +const MiddleContent = styled.div` + width: 100px; + height: 100%; + align-items: center; + padding-top: 10rem; +`; + +const RightContent = styled.div` + width: 710px; + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +`; + +const Scroll = styled.div` + width: 80%; + height: 25rem; + align-content: center; + align-items: center; + text-align: center; + margin-top: 1rem; + margin-bottom: 2rem; + overflow: auto; + padding-top: 1rem; +`; + +const SmallScroll = styled.div` + width: 80%; + height: 25rem; + align-content: center; + align-items: center; + text-align: center; + margin-top: 1.5rem; + margin-bottom: 2rem; + overflow: auto; + border: 1px solid lightgray; + border-radius: 10px; + padding-top: 1rem; +`; + +const Organization = () => { + const username = localStorage.getItem("username"); + const admin = useRecoilValue(adminState); + const [isClicked, setIsClicked] = useState(false); + const [organizationInfo, setOrganizationInfo] = useState({ + organizationName: "", + }); + const [userInfo, setUserInfo] = useState({ + username: "", + }); + const [clickedOrganizationName, setClickedOrganizationName] = useState(""); + + const { data: organizationList } = useGetAllOrganizations(username); + + const { + refetch, + isFetched, + data: memberList, + } = useGetOrganizationMemberList(clickedOrganizationName); + + const [changeMemberView, setChangeMemberView] = useState(false); + + const organizationClicked = (text) => { + setClickedOrganizationName(text); + setIsClicked(true); + }; + + React.useEffect(() => { + refetch().then(() => { + setChangeMemberView(false); + }); + }, [clickedOrganizationName, changeMemberView]); + + const changeOrganizationInfo = (name, value) => { + setOrganizationInfo((prev) => ({ ...prev, [name]: value })); + }; + + const changeUserInfo = (name, value) => { + setUserInfo((prev) => ({ ...prev, [name]: value })); + }; + + const hasBlank = (info) => { + if (Object.keys(info).find((key) => info[key] === "")) { + return true; + } else { + return false; + } + }; + + const createGroupClicked = (organizationInfo) => { + if (hasBlank(organizationInfo)) { + alert("그룹명을 작성해주세요."); + } else { + addOrganization(organizationInfo); + } + }; + + const insertUserClicked = (userInfo) => { + if (hasBlank(userInfo)) { + alert("사용자명을 작성해주세요."); + } else { + addUserInOrganization(clickedOrganizationName, userInfo); + setChangeMemberView(true); + } + }; + + const memberClicked = (username) => { + console.log(username); + if (admin) { + if (window.confirm(username + " 사용자를 그룹에서 제외하시겠습니까?")) { + deleteOrganizationMember(clickedOrganizationName, username); + setChangeMemberView(true); + } + } + }; + + return ( +
+