diff --git a/client/.eslintrc.json b/client/.eslintrc.json index d9c08bc..655620b 100644 --- a/client/.eslintrc.json +++ b/client/.eslintrc.json @@ -22,6 +22,8 @@ }, "plugins": ["react", "@typescript-eslint"], "rules": { + "react/jsx-props-no-spreading" : 0, + "react/jsx-no-useless-fragment" : 0, "no-shadow" : 0, "no-return-assign" : 0, "consistent-return" : 0, diff --git a/client/src/App.tsx b/client/src/App.tsx index 9f20baa..a4316b5 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -13,6 +13,7 @@ export const App: React.FC = () => { <> } /> + } /> } /> {/* } /> */} {/* } /> */} diff --git a/client/src/Component/Atom/LocationDropDown.tsx b/client/src/Component/Atom/LocationDropDown.tsx index b1d5d0a..ca4eb66 100644 --- a/client/src/Component/Atom/LocationDropDown.tsx +++ b/client/src/Component/Atom/LocationDropDown.tsx @@ -13,20 +13,28 @@ const InfoStyle = css` margin-left: 7px; `; -export default function LocationDropDown({ setLocSelected, id }: { setLocSelected: (value: string) => void; id: string }) { +export default function LocationDropDown({ locSelected, handleLocationSelected, id }: { locSelected: string; handleLocationSelected: (e: React.ChangeEvent) => void; id: string }) { return ( - - - - - - - - - + {locationList.map(({ id, value }) => ( + + ))} ); } + +const locationList = [ + { id: "서울", value: "서울" }, + { id: "경기", value: "경기" }, + { id: "인천", value: "인천" }, + { id: "대구", value: "대구" }, + { id: "대전", value: "대전" }, + { id: "광주", value: "광주" }, + { id: "부산", value: "부산" }, + { id: "울산", value: "울산" }, +]; diff --git a/client/src/Component/Atom/ProfileImage.tsx b/client/src/Component/Atom/ProfileImage.tsx index 2feb10a..46a42d3 100644 --- a/client/src/Component/Atom/ProfileImage.tsx +++ b/client/src/Component/Atom/ProfileImage.tsx @@ -1,12 +1,14 @@ +import React from "react"; import { css } from "@emotion/react"; import { ProfileImageType } from "@Util/type"; import { URL } from "@Util/URL"; + const defaultImage = "/Asset/meetingImage.png"; export const ProfileImage: React.FC = ({ type, onClick, ref, children, image }) => { const src = String(image).includes("/uploads") ? URL + String(image ?? defaultImage) : image ?? defaultImage; return (
- ProfileImage + {children}
); diff --git a/client/src/Component/Core/InfoImage/InfoImage.hook.tsx b/client/src/Component/Core/InfoImage/InfoImage.hook.tsx new file mode 100644 index 0000000..a97698c --- /dev/null +++ b/client/src/Component/Core/InfoImage/InfoImage.hook.tsx @@ -0,0 +1,56 @@ +import { teamState } from "@Recoil/TeamData"; +import { userState } from "@Recoil/UserData"; +import { postImage } from "@Util/data"; +import { useEffect, useRef, useState } from "react"; +import { useRecoilValue, useSetRecoilState } from "recoil"; + +export const useHandleImageEdit = (checkPathName: boolean) => { + const { id, gid } = useRecoilValue(userState); + const setUserInfo = useSetRecoilState(userState); + const setTeamInfo = useSetRecoilState(teamState); + + const handleImageEdit = (imageFile: Blob) => async () => { + const targetId = checkPathName ? id : String(gid); + const handler = checkPathName ? setUserInfo : setTeamInfo; + const url = await postImage(imageFile, targetId); + + handler((prev: any) => ({ + ...prev, + image: url, + })); + }; + + return handleImageEdit; +}; + +const initBlob = new Blob(); +const reader = new FileReader(); +const defaultImage = "/Asset/meetingImage.png"; + +export const useHandleImage = (checkPathName: boolean) => { + const [imageFile, setImageFile] = useState(initBlob); + const { image: userImage } = useRecoilValue(userState); + const { image: teamImage } = useRecoilValue(teamState); + const [profileImage, setProfileImage] = useState((checkPathName ? userImage : teamImage) ?? defaultImage); + + const changeImage = (e: React.ChangeEvent) => { + if (!e.target.files) return; + setImageFile(e.target.files[0]); + }; + + useEffect(() => { + if (imageFile === initBlob) return; + reader.onloadend = () => { + setProfileImage(reader.result); + }; + reader.readAsDataURL(imageFile); + }, [imageFile]); + + return { imageFile, profileImage, changeImage }; +}; + +export const useHandleImageClick = () => { + const imageRef = useRef(null); + const handleClickImage = () => (imageRef.current as HTMLInputElement).click(); + return { imageRef, handleClickImage }; +}; diff --git a/client/src/Component/Core/InfoImage/InfoImage.tsx b/client/src/Component/Core/InfoImage/InfoImage.tsx new file mode 100644 index 0000000..2c10df2 --- /dev/null +++ b/client/src/Component/Core/InfoImage/InfoImage.tsx @@ -0,0 +1,36 @@ +import React from "react"; +import { css } from "@emotion/react"; +import { ProfileImage } from "@Atom/ProfileImage"; +import { Button } from "@Atom/Button"; +import { useGetParams } from "@Hook/useGetParams"; +import { useHandleImage, useHandleImageClick, useHandleImageEdit } from "./InfoImage.hook"; + +export const InfoImage: React.FC = () => { + const checkPathName = useGetParams("myInfo"); + const { imageRef, handleClickImage } = useHandleImageClick(); + const { imageFile, profileImage, changeImage } = useHandleImage(checkPathName); + const handleImageEdit = () => useHandleImageEdit(checkPathName)(imageFile); + + return ( +
+ + + + +
+ ); +}; + +const TeamInfoImageContainerStyle = css` + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; +`; + +const imageInputStyle = css` + display: none; +`; diff --git a/client/src/Component/Core/index.tsx b/client/src/Component/Core/index.tsx index cfc8de9..0e632d1 100644 --- a/client/src/Component/Core/index.tsx +++ b/client/src/Component/Core/index.tsx @@ -8,3 +8,4 @@ export * from "./Modal"; export * from "./MyPageSideBar"; export * from "./NavBar/Navbar"; export * from "./Header/Header"; +export * from "./InfoImage/InfoImage"; diff --git a/client/src/Component/Hoc/InfoImageContainer.tsx b/client/src/Component/Hoc/InfoImageContainer.tsx deleted file mode 100644 index 2c600ab..0000000 --- a/client/src/Component/Hoc/InfoImageContainer.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import React, { ChangeEvent, ChangeEventHandler, useEffect, useRef, useState } from "react"; -import { css } from "@emotion/react"; -import { useRecoilValue, useSetRecoilState } from "recoil"; -import { ProfileImage } from "@Atom/ProfileImage"; -import { Button } from "@Atom/Button"; -import { postImage } from "@Util/data"; -import { userState } from "@Recoil/UserData"; -import { teamState } from "@Recoil/TeamData"; - -const defaultImage = "/Asset/meetingImage.png"; -const TeamInfoImageContainerStyle = css` - width: 100%; - height: 100%; - display: flex; - align-items: center; - justify-content: center; -`; - -const imageInputStyle = css` - display: none; -`; -export const InfoImageContainer: React.FC = () => { - const { id, gid } = useRecoilValue(userState); - const setUserInfo = useSetRecoilState(userState); - const setTeamInfo = useSetRecoilState(teamState); - - let image: string | null; - - const initBlob = new Blob(); - const imageInputTag = useRef(null); - const [profileImage, setProfileImage] = useState(null); - const [imageFile, setImageFile] = useState(initBlob); - const { image: userImage } = useRecoilValue(userState); - const { image: teamImage } = useRecoilValue(teamState); - - useEffect(() => { - image = window.location.href.includes("myinfo") ? userImage : teamImage; - setProfileImage(image ?? defaultImage); - }, [userImage, teamImage]); - - const clickImageTag = () => { - (imageInputTag.current as HTMLInputElement).click(); - }; - - const changeImage: ChangeEventHandler = (event: ChangeEvent) => { - if (!event.target.files) return; - setImageFile(event.target.files[0]); - }; - - const handleImageEdit = async () => { - let targetId; - let handler; - - if (window.location.href.includes("myinfo")) { - targetId = id; - handler = setUserInfo; - } else { - targetId = String(gid); - handler = setTeamInfo; - } - - const url = await postImage(imageFile, targetId); - - handler((prev: any) => ({ - ...prev, - image: url, - })); - }; - - useEffect(() => { - if (imageFile === initBlob) return; - const reader = new FileReader(); - reader.onloadend = () => { - setProfileImage(reader.result); - }; - reader.readAsDataURL(imageFile); - }, [imageFile]); - - return ( -
- - - - -
- ); -}; diff --git a/client/src/Component/Hoc/LoginUserRouter.tsx b/client/src/Component/Hoc/LoginUserRouter.tsx new file mode 100644 index 0000000..7c289cc --- /dev/null +++ b/client/src/Component/Hoc/LoginUserRouter.tsx @@ -0,0 +1,11 @@ +import React from "react"; +import { checkLogin, passToLoginPage } from "@Util/."; +import { ChildrenType } from "@Util/type"; + +export const LoginUserRouter = ({ children }: ChildrenType) => { + // if (!checkLogin()) { + // passToLoginPage(); + // return null; + // } + return <>{children}; +}; diff --git a/client/src/Component/Hoc/index.tsx b/client/src/Component/Hoc/index.tsx index 3acd098..42d6de4 100644 --- a/client/src/Component/Hoc/index.tsx +++ b/client/src/Component/Hoc/index.tsx @@ -1,5 +1,4 @@ export * from "./InfoContainer"; -export * from "./InfoImageContainer"; export * from "./ProfileImageContainer"; export * from "./TeamButtonContainer"; export * from "./UserContainer"; diff --git a/client/src/Component/Molecules/Team/TeamSettingButtonContainer.tsx b/client/src/Component/Molecules/Team/TeamSettingButtonContainer.tsx index d3306e5..3f1a3b9 100644 --- a/client/src/Component/Molecules/Team/TeamSettingButtonContainer.tsx +++ b/client/src/Component/Molecules/Team/TeamSettingButtonContainer.tsx @@ -1,27 +1,23 @@ -import { useRef, useState } from "react"; +import { useRef } from "react"; import { Button } from "@Atom/."; import useDropDownCloseEvent from "@Hook/useDropDownCloseEvent"; import { TeamButtonContainer } from "@Hoc/."; -import InviteModal from "../../Template/Modal/InviteModal"; +import InviteModal from "@Template/Modal/InviteModal"; +import { useToggleHook } from "@Hook/useToggleHook"; type props = { clickUpdateButton: React.MouseEventHandler; clickExitButton: React.MouseEventHandler }; export const TeamSettingButtonContainer = ({ clickUpdateButton, clickExitButton }: props) => { - const [inviteModalState, setInviteModalState] = useState(false); + const [inviteModalState, handleToggleInvite, handleFalseInvite] = useToggleHook(); const modalRef = useRef(null); - useDropDownCloseEvent(modalRef, () => setInviteModalState(false)); + useDropDownCloseEvent(modalRef, handleFalseInvite); return (
- - {inviteModalState && } + {inviteModalState && }