diff --git a/components/common/CardContent/CardContent.tsx b/components/common/CardContent/CardContent.tsx index ab45e0b306..afbdf21aac 100644 --- a/components/common/CardContent/CardContent.tsx +++ b/components/common/CardContent/CardContent.tsx @@ -1,8 +1,8 @@ import { KebabMenu } from "@components/folder/KebabMenu/KebabMenu"; import * as S from "./CardContentStyled"; -import { MouseEvent, useState } from "react"; -import { FolderListDataForm } from "../../../types/DataForm"; import Image from "next/image"; +import { usePortalContents } from "@hooks/usePortalContents"; +import { FolderListDataForm } from "@data-access/axios/getCategory"; interface CardContentProps { elapsedTime: string; @@ -11,6 +11,8 @@ interface CardContentProps { isHovered: boolean; currentLocation: string; selectURL: string; + folderList: FolderListDataForm[]; + linkId: number; } export const CardContent = ({ @@ -20,28 +22,28 @@ export const CardContent = ({ isHovered, currentLocation, selectURL, + folderList, + linkId, }: CardContentProps) => { - const [isOpened, setIsClick] = useState(false); - const className = isHovered - ? "CardContent CardContent-hovered" - : "CardContent"; - - const handleClickMenu = (e: MouseEvent) => { - e.preventDefault(); - setIsClick(isOpened === false ? true : false); - }; + const kebabMenu = usePortalContents(); return ( -
+ <> {elapsedTime} - {currentLocation === "/folder" && ( - + {!currentLocation.includes("shared") && ( + 메뉴 보기 )} - {isOpened && } -
+ {kebabMenu.isOpenModal && ( + + )} + {description} {createdAt} diff --git a/components/common/CardItem/CardItem.tsx b/components/common/CardItem/CardItem.tsx index aeede60c98..df799901d0 100644 --- a/components/common/CardItem/CardItem.tsx +++ b/components/common/CardItem/CardItem.tsx @@ -13,6 +13,8 @@ export const CardItem = ({ image_source, description, created_at, + folderList, + linkId, }: CardInfoDataForm) => { const [isHovered, setIsHovered] = useState(false); const location = useRouter(); @@ -34,6 +36,8 @@ export const CardItem = ({ isHovered={isHovered} currentLocation={currentLocation} selectURL={url} + folderList={folderList} + linkId={linkId} /> diff --git a/components/common/Layout/Layout.tsx b/components/common/Layout/Layout.tsx index 5f25f7766c..1bbea0bdf6 100644 --- a/components/common/Layout/Layout.tsx +++ b/components/common/Layout/Layout.tsx @@ -1,21 +1,8 @@ import Footer from "../Footer"; -import { PropsWithChildren, useEffect } from "react"; +import { PropsWithChildren } from "react"; import { NavigationBar } from "../NavigationBar"; -import { useRouter } from "next/router"; export const Layout = ({ children }: PropsWithChildren) => { - const router = useRouter(); - const currentPath = router.pathname; - - useEffect(() => { - const localStorageToken = localStorage.getItem("accessToken"); - if (currentPath !== "/") { - if (localStorageToken === null) { - router.push("/signin"); - } - } - }, [currentPath, router]); - return ( <>
diff --git a/components/common/Modals/AddFolder/AddFolder.tsx b/components/common/Modals/AddFolder/AddFolder.tsx new file mode 100644 index 0000000000..a5c810b5d9 --- /dev/null +++ b/components/common/Modals/AddFolder/AddFolder.tsx @@ -0,0 +1,39 @@ +import { ModalInput } from "../ModalElements/ModalInput"; +import Modal from "../Modal"; +import { BaseModalProps } from "../ModalProp"; +import { PrimaryButton } from "@styles/common/PrimaryButton"; +import { postNewFolder } from "@data-access/axios/postNewFolder"; +import { useMutation } from "@tanstack/react-query"; +import { useInputValue } from "@hooks/useInputValue"; +import { MouseEvent } from "react"; + +export function AddFolder({ handleCloseModal }: BaseModalProps) { + const { insertValue, onChange } = useInputValue(); + const createFolderMutation = useMutation({ + mutationFn: (createFolderName: string) => + postNewFolder({ folderName: createFolderName }), + }); + + const handleCreateNewFolder = async ( + event: MouseEvent + ) => { + const createFolderName = insertValue; + + createFolderMutation.mutate(createFolderName); + handleCloseModal(event); + }; + + return ( + + + + 추가하기 + + + ); +} diff --git a/components/common/Modals/AddFolder/index.ts b/components/common/Modals/AddFolder/index.ts new file mode 100644 index 0000000000..8e8c4420bd --- /dev/null +++ b/components/common/Modals/AddFolder/index.ts @@ -0,0 +1 @@ +export * from "./AddFolder"; diff --git a/components/common/Modals/AddFolderContent/AddFolderContent.tsx b/components/common/Modals/AddFolderContent/AddFolderContent.tsx deleted file mode 100644 index 0584b1dfd5..0000000000 --- a/components/common/Modals/AddFolderContent/AddFolderContent.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import { ModalInput } from "../ModalElements/ModalInput"; -import { ModalButtonBlue } from "../ModalElements/ModalButtonBlue"; - -export function AddFolderContent() { - return ( - <> - - 추가하기 - - ); -} diff --git a/components/common/Modals/AddFolderContent/index.ts b/components/common/Modals/AddFolderContent/index.ts deleted file mode 100644 index b990ef07b9..0000000000 --- a/components/common/Modals/AddFolderContent/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./AddFolderContent"; diff --git a/components/common/Modals/AddToFolder/AddToFolder.tsx b/components/common/Modals/AddToFolder/AddToFolder.tsx index d97fff575e..e9f5daa0db 100644 --- a/components/common/Modals/AddToFolder/AddToFolder.tsx +++ b/components/common/Modals/AddToFolder/AddToFolder.tsx @@ -1,21 +1,51 @@ -import { ModalButtonBlue } from "../ModalElements/ModalButtonBlue"; import * as S from "./AddToFolderStyled"; +import Modal from "../Modal"; import { AddToFolderProps } from "../ModalProp"; +import { PrimaryButton } from "@styles/common/PrimaryButton"; +import { useMutation } from "@tanstack/react-query"; +import { postAddToFolder } from "@data-access/axios/postAddToFolder"; +import { MouseEvent, useState } from "react"; + +export function AddToFolder({ + linkURL, + folderList, + handleCloseModal, +}: AddToFolderProps) { + const [selectFolderId, setSelectFolderId] = useState(); + const addToFolderMutation = useMutation({ + mutationFn: ({ url, folderId }: { url: string; folderId: number }) => + postAddToFolder({ url: url, folderId: folderId }), + }); + + const handleFolderId = (event: MouseEvent) => { + setSelectFolderId(Number(event.currentTarget.id)); + }; + + const handleAddToFolder = async (event: MouseEvent) => { + if (linkURL && selectFolderId) { + addToFolderMutation.mutate({ url: linkURL, folderId: selectFolderId }); + } + }; -export function AddToFolder({ linkURL, data }: AddToFolderProps) { return ( - <> + {linkURL} - {data?.map((folder) => ( - + {folderList?.map((folder) => ( + {folder.name} - {folder.link.count}개 링크 + {folder.link_count}개 링크 ))} - 삭제하기 - + + 추가하기 + + ); } diff --git a/components/common/Modals/AddToFolder/AddToFolderStyled.ts b/components/common/Modals/AddToFolder/AddToFolderStyled.ts index 7b0587ac6a..86459d8f81 100644 --- a/components/common/Modals/AddToFolder/AddToFolderStyled.ts +++ b/components/common/Modals/AddToFolder/AddToFolderStyled.ts @@ -1,5 +1,10 @@ import styled from "styled-components"; +export const AddToFolderContainer = styled.div` + width: 30rem; + display: flex; + flex-direction: column; +`; export const FolderListContainer = styled.div` display: flex; flex-direction: column; @@ -8,7 +13,7 @@ export const FolderListContainer = styled.div` overflow: hidden scroll; `; -export const SelectFolder = styled.div` +export const SelectFolder = styled.button` display: flex; flex-direction: row; justify-content: flex-start; @@ -22,10 +27,15 @@ export const SelectFolder = styled.div` `; export const SelectLink = styled.p` + width: 30rem; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; color: var(--gray60); font-size: 1.4rem; line-height: 2.2rem; text-align: center; + margin: 0.5rem 0 2.5rem 0; `; export const FolderName = styled.p` diff --git a/components/common/Modals/DeleteFolder/DeleteFolder.tsx b/components/common/Modals/DeleteFolder/DeleteFolder.tsx index 62f55ef797..558a82983c 100644 --- a/components/common/Modals/DeleteFolder/DeleteFolder.tsx +++ b/components/common/Modals/DeleteFolder/DeleteFolder.tsx @@ -1,12 +1,30 @@ import * as S from "./DeleteFolderStyled"; import { ModalButtonRed } from "../ModalElements/ModalButtonRed"; import { DeleteFolderProps } from "../ModalProp"; +import Modal from "../Modal"; +import { useMutation } from "@tanstack/react-query"; +import { deleteFolder } from "@data-access/axios/deleteFolder"; +import { MouseEvent } from "react"; + +export default function DeleteFolder({ + selectFolder, + folderId, + handleCloseModal, +}: DeleteFolderProps) { + const deleteFolderMutation = useMutation({ + mutationFn: ({ folderId }: { folderId: number | string }) => + deleteFolder({ folderId }), + }); + + const handleDeleteFolder = (event: MouseEvent) => { + deleteFolderMutation.mutate({ folderId: folderId }); + handleCloseModal(event); + }; -export default function DeleteFolder({ selectFolder }: DeleteFolderProps) { return ( - <> + {selectFolder} - 삭제하기 - + 삭제하기 + ); } diff --git a/components/common/Modals/DeleteLink/DeleteLink.tsx b/components/common/Modals/DeleteLink/DeleteLink.tsx index 1d9360e58c..1d8ce6d36d 100644 --- a/components/common/Modals/DeleteLink/DeleteLink.tsx +++ b/components/common/Modals/DeleteLink/DeleteLink.tsx @@ -1,12 +1,30 @@ import { ModalButtonRed } from "../ModalElements/ModalButtonRed"; import * as S from "./DeleteLinkStyled"; import { DeleteLinkProps } from "../ModalProp"; +import Modal from "../Modal"; +import { useMutation } from "@tanstack/react-query"; +import { deleteLink } from "@data-access/axios/deleteLink"; +import { MouseEvent } from "react"; + +export default function DeleteLink({ + deleteURL, + handleCloseModal, + linkId, +}: DeleteLinkProps) { + const deleteLinkMutation = useMutation({ + mutationFn: ({ linkId }: { linkId: number }) => deleteLink({ linkId }), + }); + + const handleDeleteLink = (event: MouseEvent) => { + deleteLinkMutation.mutate({ linkId: Number(event.currentTarget.id) }); + }; -export default function DeleteLink({ deleteURL }: DeleteLinkProps) { return ( - <> + {deleteURL} - 삭제하기 - + + 삭제하기 + + ); } diff --git a/components/common/Modals/Modal/Modal.tsx b/components/common/Modals/Modal/Modal.tsx index ace8102283..9d98caf438 100644 --- a/components/common/Modals/Modal/Modal.tsx +++ b/components/common/Modals/Modal/Modal.tsx @@ -1,25 +1,20 @@ import ModalPortal from "@components/Portal"; -import { ModalCloseButton } from "../ModalElements/ModalCloseButton"; -import { ModalContainer } from "../ModalElements/ModalContainer"; +import { ModalProps } from "../ModalProp"; import { ModalDim } from "../ModalElements/ModalDim"; +import { ModalContainer } from "../ModalElements/ModalContainer"; +import { ModalCloseButton } from "../ModalElements/ModalCloseButton"; import { ModalTitle } from "../ModalElements/ModalTitle"; -import { ModalProps } from "../ModalProp"; -import { ModalContext } from "@components/common/RefactorModal/ModalContext"; -import { useContext } from "react"; - -export default function Modal({ children, title }: ModalProps) { - const { handleModalState } = useContext(ModalContext); - function handleCloseModal() { - handleModalState({ - isOpenModal: false, - }); - } +export default function Modal({ + children, + title, + handleCloseModal, +}: ModalProps) { return ( - + {title} {children} diff --git a/components/common/Modals/ModalElements/ModalButtonBlue.ts b/components/common/Modals/ModalElements/ModalButtonBlue.ts deleted file mode 100644 index 8d1d6862e6..0000000000 --- a/components/common/Modals/ModalElements/ModalButtonBlue.ts +++ /dev/null @@ -1,12 +0,0 @@ -import styled from "styled-components"; - -export const ModalButtonBlue = styled.button` - width: 28rem; - border-radius: 0.8rem; - padding: 1.6rem 2rem; - background: linear-gradient(90.99deg, #6d6afe 0.12%, #6ae3fe 101.84%); - font-size: 1.6rem; - line-height: 1.909rem; - font-weight: 600; - color: var(--gray-light); -`; diff --git a/components/common/Modals/ModalElements/ModalCloseButton.tsx b/components/common/Modals/ModalElements/ModalCloseButton.tsx index 724b0e6d60..e1f87a7c1b 100644 --- a/components/common/Modals/ModalElements/ModalCloseButton.tsx +++ b/components/common/Modals/ModalElements/ModalCloseButton.tsx @@ -12,9 +12,9 @@ export const CloseButtonModal = styled.button` right: 1.2rem; `; -export function ModalCloseButton({ handleModalClose }: BaseModalProps) { +export function ModalCloseButton({ handleCloseModal }: BaseModalProps) { return ( - + X ); diff --git a/components/common/Modals/ModalProp.ts b/components/common/Modals/ModalProp.ts index ef312a5486..7a917d5236 100644 --- a/components/common/Modals/ModalProp.ts +++ b/components/common/Modals/ModalProp.ts @@ -1,25 +1,34 @@ +import { FolderListDataForm } from "@data-access/axios/getCategory"; import { MouseEvent } from "react"; -import { FolderListDataForm } from "../../../types/DataForm"; export interface BaseModalProps { - isOpenModal?: boolean; - handleModalClose: (e: MouseEvent) => void; + handleCloseModal: (event: MouseEvent) => void; } -export interface DeleteLinkProps { +export interface DeleteLinkProps extends BaseModalProps { deleteURL: string; + linkId: number; } -export interface DeleteFolderProps { +export interface DeleteFolderProps extends BaseModalProps { selectFolder: string; + folderId: number; } -export interface ModalProps { +export interface ModalProps extends BaseModalProps { children: JSX.Element | JSX.Element[]; title: string; } -export interface AddToFolderProps { +export interface AddToFolderProps extends BaseModalProps { linkURL: string | undefined; - data: FolderListDataForm[] | undefined; + folderList: FolderListDataForm[] | undefined; +} + +export interface RenameFolderProps extends BaseModalProps { + selectFolderId: number; +} + +export interface SharedFolderProps extends BaseModalProps { + selectFolder: string; } diff --git a/components/common/Modals/RenameModal/RenameModal.tsx b/components/common/Modals/RenameModal/RenameModal.tsx index f67d4efa03..be2409785c 100644 --- a/components/common/Modals/RenameModal/RenameModal.tsx +++ b/components/common/Modals/RenameModal/RenameModal.tsx @@ -1,13 +1,47 @@ +import { PrimaryButton } from "@styles/common/PrimaryButton"; import Modal from "../Modal"; -import { ModalButtonBlue } from "../ModalElements/ModalButtonBlue"; import { ModalInput } from "../ModalElements/ModalInput"; -import { BaseModalProps } from "../ModalProp"; +import { RenameFolderProps } from "../ModalProp"; +import { MouseEvent } from "react"; +import { useInputValue } from "@hooks/useInputValue"; +import { putRenameFolder } from "@data-access/axios/putRenameFolder"; +import { useMutation } from "@tanstack/react-query"; + +export function RenameModal({ + handleCloseModal, + selectFolderId, +}: RenameFolderProps) { + const { insertValue, onChange } = useInputValue(); + const renameFolderMutation = useMutation({ + mutationFn: ({ + folderId, + folderTitle, + }: { + folderId: number; + folderTitle: string; + }) => putRenameFolder({ folderId, folderTitle }), + }); + + async function handleRenameFolder(event: MouseEvent) { + if (insertValue) { + renameFolderMutation.mutate({ + folderId: selectFolderId, + folderTitle: insertValue, + }); + } + handleCloseModal(event); + } -export function RenameModal() { return ( - <> - - 변경하기 - + + + + 변경하기 + + ); } diff --git a/components/common/Modals/SharedFolder/SharedFolder.tsx b/components/common/Modals/SharedFolder/SharedFolder.tsx index 96fb666473..3ee25c7df0 100644 --- a/components/common/Modals/SharedFolder/SharedFolder.tsx +++ b/components/common/Modals/SharedFolder/SharedFolder.tsx @@ -1,8 +1,9 @@ import * as S from "./SharedFolderStyled"; -import { DeleteFolderProps } from "../ModalProp"; +import { SharedFolderProps } from "../ModalProp"; import { handleCopyClipBoard } from "@util/copyClipBoard"; import Link from "next/link"; import { shareKakao } from "@util/sharedKakao"; +import Modal from "../Modal"; declare global { interface Window { @@ -10,13 +11,16 @@ declare global { } } -export function SharedFolder({ selectFolder }: DeleteFolderProps) { +export function SharedFolder({ + selectFolder, + handleCloseModal, +}: SharedFolderProps) { const handleSharedKakao = () => { shareKakao("https://codingaring-week11-linkbrary.netlify.app"); }; https: return ( - <> + {selectFolder} @@ -45,6 +49,6 @@ export function SharedFolder({ selectFolder }: DeleteFolderProps) { 링크 복사 - + ); } diff --git a/components/common/Modals/SharedFolder/SharedFolderStyled.ts b/components/common/Modals/SharedFolder/SharedFolderStyled.ts index 7cbb4ff8a5..e05cec4bd0 100644 --- a/components/common/Modals/SharedFolder/SharedFolderStyled.ts +++ b/components/common/Modals/SharedFolder/SharedFolderStyled.ts @@ -32,6 +32,7 @@ export const SharedButton = styled.button` display: flex; flex-direction: column; justify-content: center; + align-items: center; gap: 1rem; & img { diff --git a/components/common/NavigationBar/NavigationBar.tsx b/components/common/NavigationBar/NavigationBar.tsx index 5a490d4825..dd2cca78b5 100644 --- a/components/common/NavigationBar/NavigationBar.tsx +++ b/components/common/NavigationBar/NavigationBar.tsx @@ -3,38 +3,25 @@ import { Profile } from "./Profile"; import { LOGO_IMAGE, TEXT } from "./constant"; import { useRouter } from "next/router"; import { ROUTE } from "@util/constant"; -import { useEffectOnce } from "@hooks/useEffectOnce"; import { getLoginUserInfo } from "@data-access/getLoginUserInfo"; -import { useContext, useState } from "react"; +import { useContext, useEffect, useState } from "react"; import { UserContext } from "context/UserContext"; +import { useQuery } from "@tanstack/react-query"; export const NavigationBar = () => { const { handleUserDataState } = useContext(UserContext); - const router = useRouter(); - const [profile, setProfile] = useState({ - auth_id: "", - email: "", - image_source: "", - }); const Location = useRouter(); const LocationPath = Location.pathname; + const { data: profile } = useQuery({ + queryKey: ["loginUserProfile"], + queryFn: getLoginUserInfo, + }); - async function handleLoadUserInfo() { - try { - const { data } = await getLoginUserInfo(); - const { email, image_source, auth_id } = data[0] || []; - setProfile({ - auth_id: auth_id, - email: email, - image_source: image_source, - }); - handleUserDataState({ userId: auth_id }); - } catch (error) { - router.push("/signin"); + useEffect(() => { + if (profile) { + handleUserDataState({ isLogin: true, userId: profile.id }); } - } - - useEffectOnce(handleLoadUserInfo); + }, [handleUserDataState, profile]); return ( diff --git a/components/common/NavigationBar/NavigationBarStyled.ts b/components/common/NavigationBar/NavigationBarStyled.ts index 2a141b5d98..09e8f6c7eb 100644 --- a/components/common/NavigationBar/NavigationBarStyled.ts +++ b/components/common/NavigationBar/NavigationBarStyled.ts @@ -13,7 +13,7 @@ export const NavigationBarContainer = styled.header<{ pathName: string }>` position: sticky; top: 0; `} - z-index: var(--z-index-nav); + z-index: 1; width: 100%; background-color: var(--light-blue); `; diff --git a/components/common/RefactorModal/ModalContext.ts b/components/common/RefactorModal/ModalContext.ts deleted file mode 100644 index f15e9d6691..0000000000 --- a/components/common/RefactorModal/ModalContext.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { FolderListDataForm } from "../../../types/DataForm"; -import React from "react"; - -export type ModalContextType = { - modalStateProperty: { - isOpenModal: boolean; - selectURL: string; - data: FolderListDataForm[] | undefined; - selectFolder: string; - modalType: string; - selectFolderId: string; - }; - handleModalState: ( - newState: Partial - ) => void; -}; - -export const ModalContextInitial: ModalContextType = { - modalStateProperty: { - isOpenModal: false, - selectURL: "", - data: [], - selectFolder: "", - modalType: "", - selectFolderId: "", - }, - handleModalState: () => {}, -}; - -export const ModalContext = React.createContext(ModalContextInitial); diff --git a/components/common/RefactorModal/ModalProvider.tsx b/components/common/RefactorModal/ModalProvider.tsx deleted file mode 100644 index bd5446ee36..0000000000 --- a/components/common/RefactorModal/ModalProvider.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { ReactNode, useState } from "react"; -import { - ModalContext, - ModalContextInitial, - ModalContextType, -} from "./ModalContext"; - -export function ModalProvider({ children }: { children: ReactNode }) { - const [modalState, setModalState] = useState< - ModalContextType["modalStateProperty"] - >(ModalContextInitial["modalStateProperty"]); - - function handleModalState( - newState: Partial - ) { - setModalState((prevState) => ({ - ...prevState, - ...newState, - })); - } - - const modalStateValue: ModalContextType = { - modalStateProperty: modalState, - handleModalState, - }; - - return ( - - {children} - - ); -} diff --git a/components/common/RefactorModal/RefactorModal.tsx b/components/common/RefactorModal/RefactorModal.tsx deleted file mode 100644 index ca3fe18def..0000000000 --- a/components/common/RefactorModal/RefactorModal.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import { useContext } from "react"; -import { AddFolderContent } from "../Modals/AddFolderContent"; -import { AddToFolder } from "../Modals/AddToFolder"; -import DeleteFolder from "../Modals/DeleteFolder"; -import DeleteLink from "../Modals/DeleteLink"; -import { RenameModal } from "../Modals/RenameModal"; -import { SharedFolder } from "../Modals/SharedFolder/SharedFolder"; -import { ModalContext } from "./ModalContext"; -import Modal from "../Modals/Modal"; - -export function RefactorModal() { - const { modalStateProperty } = useContext(ModalContext); - const { modalType, isOpenModal, selectURL, selectFolder, data } = - modalStateProperty; - - let modalContent; - let modalTitle = ""; - - switch (modalType) { - case "deleteLink": - modalContent = ; - modalTitle = "링크 삭제"; - break; - case "addToFolder": - modalContent = ; - modalTitle = "폴더에 추가"; - break; - case "addFolderContent": - modalContent = ; - modalTitle = "폴더 추가"; - break; - case "sharedFolder": - modalContent = ; - modalTitle = "폴더 공유"; - break; - case "renameModal": - modalContent = ; - modalTitle = "폴더 이름 변경"; - break; - case "deleteFolder": - modalContent = ; - modalTitle = "폴더 삭제"; - break; - default: - modalContent = <>; - } - - return isOpenModal ? {modalContent} : <>; -} diff --git a/components/folder/CategoryNav/CategoryNavButtons/CategoryNavButtons.tsx b/components/folder/CategoryNav/CategoryNavButtons/CategoryNavButtons.tsx index 6d5bb30382..e434284903 100644 --- a/components/folder/CategoryNav/CategoryNavButtons/CategoryNavButtons.tsx +++ b/components/folder/CategoryNav/CategoryNavButtons/CategoryNavButtons.tsx @@ -1,9 +1,10 @@ -import { MouseEvent, useContext, useState } from "react"; import { DELETE_ICON, RENAME_ICON, SHARED_ICON } from "./constant"; import * as S from "./CategoryNavButtonsStyled"; import Image from "next/image"; -import { ModalContext } from "@components/common/RefactorModal/ModalContext"; -import { RefactorModal } from "@components/common/RefactorModal/RefactorModal"; +import { usePortalContents } from "@hooks/usePortalContents"; +import { RenameModal } from "@components/common/Modals/RenameModal"; +import DeleteFolder from "@components/common/Modals/DeleteFolder"; +import { SharedFolder } from "@components/common/Modals/SharedFolder/SharedFolder"; export function CategoryNavButtons({ selectFolder, @@ -12,52 +13,53 @@ export function CategoryNavButtons({ selectFolder: string; folderId: string; }) { - const { handleModalState } = useContext(ModalContext); - - const handleShowModal = (e: MouseEvent) => { - e.preventDefault(); - - switch (e.currentTarget.id) { - case "sharedFolder": - handleModalState({ - isOpenModal: true, - modalType: "sharedFolder", - selectFolder: selectFolder, - selectFolderId: folderId, - }); - break; - case "renameModal": - handleModalState({ - isOpenModal: true, - modalType: "renameModal", - }); - break; - case "deleteFolder": - handleModalState({ - isOpenModal: true, - modalType: "deleteFolder", - selectFolder: selectFolder, - }); - break; - } - }; + const shardFolderModal = usePortalContents(); + const renameModal = usePortalContents(); + const deleteFolderModal = usePortalContents(); return ( <> - - + {shardFolderModal.isOpenModal && ( + + )} + {renameModal.isOpenModal && ( + + )} + {deleteFolderModal.isOpenModal && ( + + )} + 공유하기를 나타내는 아이콘

공유

- + 이름 변경하기를 나타내는 아이콘

이름 변경

- + 삭제하기를 나타내는 아이콘 diff --git a/components/folder/FolderContent/FolderContent.tsx b/components/folder/FolderContent/FolderContent.tsx index 11cb145c9b..e7630b0c39 100644 --- a/components/folder/FolderContent/FolderContent.tsx +++ b/components/folder/FolderContent/FolderContent.tsx @@ -1,50 +1,50 @@ import * as S from "./FolderContentStyled"; -import { useEffect, useState, MouseEvent, useContext } from "react"; +import { useEffect, useState, MouseEvent } from "react"; import { CategoryNav } from "../CategoryNav/CategoryNav"; -import { FolderListDataForm, getFolderDataForm } from "../../../types/DataForm"; import { useRecoilValue } from "recoil"; import { searchState } from "recoil/SearchKeyWord"; -import { getFolders } from "@data-access/getFolders"; +import { getFolders } from "@data-access/axios/getFolders"; import { SearchResultComment } from "@components/common/SearchResultComment"; import { Button } from "../CategoryButton/CategoryButtonStyled"; import { EmptyLink } from "@components/common/EmptyLink"; import { CardList } from "@components/common/CardList"; import { CardItem } from "@components/common/CardItem"; -import { RefactorModal } from "@components/common/RefactorModal/RefactorModal"; -import { ModalContext } from "@components/common/RefactorModal/ModalContext"; import { useRouter } from "next/router"; +import { FolderListDataForm } from "@data-access/axios/getCategory"; +import { usePortalContents } from "@hooks/usePortalContents"; +import { AddFolder } from "@components/common/Modals/AddFolder"; +import { useQuery } from "@tanstack/react-query"; interface LoadFolderDataProps { folderId: string; searchKeyWord: string; } -export function FolderContent({ data }: { data: FolderListDataForm[] }) { - const [folder, setFolder] = useState([]); +interface FolderContents { + id: number; + favorite: boolean; + created_at: string; + url: string; + title: string; + image_source: string; + description: string; +} + +export function FolderContent({ + folderInfo, +}: { + folderInfo: FolderListDataForm[] | undefined; +}) { + const [folder, setFolder] = useState([]); const [folderId, setFolderId] = useState(""); const [activeCategoryName, setActiveCategoryName] = useState("전체"); - const { handleModalState } = useContext(ModalContext); const searchKeyWord = useRecoilValue(searchState); const router = useRouter(); - - const handleLoadFolder = async ({ - folderId, - searchKeyWord, - }: LoadFolderDataProps) => { - const { data } = await getFolders(folderId); - setFolder(data); - - if (searchKeyWord) { - setFolder((prevFolder) => - prevFolder.filter( - (link) => - link.description?.includes(searchKeyWord) || - link.url?.includes(searchKeyWord) || - link.title?.includes(searchKeyWord) - ) - ); - } - }; + const addFolderModal = usePortalContents(); + const { data } = useQuery({ + queryKey: [`folderContents-${folderId}`], + queryFn: () => getFolders({ folderId: Number(folderId) }), + }); const handleCategoryActive = (e: MouseEvent) => { setActiveCategoryName(e.currentTarget.value); @@ -54,36 +54,54 @@ export function FolderContent({ data }: { data: FolderListDataForm[] }) { router.push(folderPath); }; - const handleShowModal = () => { - handleModalState({ isOpenModal: true, modalType: "addFolderContent" }); - }; - useEffect(() => { + const handleLoadFolder = async ({ searchKeyWord }: LoadFolderDataProps) => { + if (data) { + setFolder(data); + } + + if (searchKeyWord) { + setFolder((prevFolder) => + prevFolder.filter( + (link) => + link.description?.includes(searchKeyWord) || + link.url?.includes(searchKeyWord) || + link.title?.includes(searchKeyWord) + ) + ); + } + }; handleLoadFolder({ folderId, searchKeyWord }); - }, [folderId, searchKeyWord]); + }, [folderId, searchKeyWord, data]); return ( <> - + {addFolderModal.isOpenModal && ( + + )} {searchKeyWord && } - - {data.map((category) => ( - - ))} + {folderInfo && + folderInfo.map((category) => ( + + ))} - + 폴더 추가 + @@ -91,21 +109,23 @@ export function FolderContent({ data }: { data: FolderListDataForm[] }) { activeCategoryName={activeCategoryName} folderId={folderId} /> - {!folder.length ? ( - - ) : ( - - {folder?.map((link) => ( + + {folder && folder.length !== 0 ? ( + folder.map((link) => ( - ))} - - )} + )) + ) : ( + + )} + ); } diff --git a/components/folder/FolderHeader/FolderHeader.tsx b/components/folder/FolderHeader/FolderHeader.tsx index 9466f2a68b..ccf21655d9 100644 --- a/components/folder/FolderHeader/FolderHeader.tsx +++ b/components/folder/FolderHeader/FolderHeader.tsx @@ -1,21 +1,22 @@ -import { forwardRef, useEffect, useState } from "react"; -import { useGetUser as getUser } from "@data-access/useGetUser"; -import { FolderListDataForm } from "../../../types/DataForm"; -import { DEFAULT_IMAGE } from "@components/common/CardImage/constant"; +import { forwardRef } from "react"; +import * as S from "./FolderHeaderStyled"; import { NavigationBar } from "@components/common/NavigationBar"; import { AddLinkBar } from "@components/shared/AddLinkBar/AddLinkBar"; -import * as S from "./FolderHeaderStyled"; +import { FolderListDataForm } from "@data-access/axios/getCategory"; const FolderHeader = forwardRef( ( - { data, isFloating }: { data: FolderListDataForm[]; isFloating: boolean }, + { + folderInfo, + isFloating, + }: { folderInfo: FolderListDataForm[] | undefined; isFloating: boolean }, ref ) => { return (
}> - - + +
); diff --git a/components/folder/KebabMenu/KebabMenu.tsx b/components/folder/KebabMenu/KebabMenu.tsx index bb24067965..018c4a7edf 100644 --- a/components/folder/KebabMenu/KebabMenu.tsx +++ b/components/folder/KebabMenu/KebabMenu.tsx @@ -1,62 +1,45 @@ -import { useContext, useEffect, useState } from "react"; import * as S from "./KebabMenuStyled"; -import { MouseEvent } from "react"; -import { ModalContext } from "@components/common/RefactorModal/ModalContext"; -import { RefactorModal } from "@components/common/RefactorModal/RefactorModal"; -import { getCategory } from "@data-access/getCategory"; -import { useEffectOnce } from "@hooks/useEffectOnce"; +import { usePortalContents } from "@hooks/usePortalContents"; +import DeleteLink from "@components/common/Modals/DeleteLink"; +import { AddToFolder } from "@components/common/Modals/AddToFolder"; +import { FolderListDataForm } from "@data-access/axios/getCategory"; -interface Props { +interface KebabProps { selectURL: string; + folderList: FolderListDataForm[]; + linkId: number; } -export function KebabMenu({ selectURL }: Props) { - const [categoryList, setCategoryList] = useState(); - const { handleModalState } = useContext(ModalContext); - - const handleShowModal = (e: MouseEvent) => { - e.preventDefault(); - - const handleCategoryList = () => { - const { data }: any = getCategory(); - setCategoryList(data); - }; - - handleCategoryList(); - - switch (e.currentTarget.id) { - case "deleteLink": - handleModalState({ - isOpenModal: true, - selectURL: selectURL, - modalType: "deleteLink", - }); - break; - case "addToFolder": - handleModalState({ - isOpenModal: true, - selectURL: selectURL, - data: categoryList, - modalType: "addToFolder", - }); - } - }; +export function KebabMenu({ selectURL, folderList, linkId }: KebabProps) { + const deleteLinkModal = usePortalContents(); + const addToFolderModal = usePortalContents(); return ( <> - + {deleteLinkModal.isOpenModal && ( + + )} + {addToFolderModal.isOpenModal && ( + + )} 삭제하기 폴더에 추가 diff --git a/components/home/LandingHeader/LandingHeader.tsx b/components/home/LandingHeader/LandingHeader.tsx index 0dbdf4492f..c424536a34 100644 --- a/components/home/LandingHeader/LandingHeader.tsx +++ b/components/home/LandingHeader/LandingHeader.tsx @@ -2,8 +2,22 @@ import Link from "next/link"; import { HERO_IMAGE_SRC } from "../constant"; import * as S from "./LandingHeaderStyled"; import Image from "next/image"; +import { useRouter } from "next/router"; +import { useContext, useEffect } from "react"; +import { UserContext } from "context/UserContext"; export default function LandingHeader() { + const router = useRouter(); + const { loginData } = useContext(UserContext); + + const handleGoFolders = () => { + if (loginData.isLogin) { + router.push("/folder"); + } else { + router.push("/signin"); + } + }; + return ( @@ -11,7 +25,9 @@ export default function LandingHeader() { 쉽게 저장하고 관리해 보세요 - 링크 추가하기 + + 링크 추가하기 + 링크브러리 메인 화면 diff --git a/components/shared/AddLinkBar/AddLinkBar.tsx b/components/shared/AddLinkBar/AddLinkBar.tsx index 05da15794f..826135e912 100644 --- a/components/shared/AddLinkBar/AddLinkBar.tsx +++ b/components/shared/AddLinkBar/AddLinkBar.tsx @@ -1,41 +1,37 @@ import { useState, ChangeEvent, useContext } from "react"; import * as S from "./AddLinkBarStyled"; import { ADD_ICON } from "./constant"; -import { FolderListDataForm } from "../../../types/DataForm"; -import { ModalContext } from "@components/common/RefactorModal/ModalContext"; -import { RefactorModal } from "@components/common/RefactorModal/RefactorModal"; +import { FolderListDataForm } from "@data-access/axios/getCategory"; +import { usePortalContents } from "@hooks/usePortalContents"; +import { AddToFolder } from "@components/common/Modals/AddToFolder"; export function AddLinkBar({ - data, + folderInfo, isFloating = false, }: { - data: FolderListDataForm[]; + folderInfo: FolderListDataForm[] | undefined; isFloating?: boolean; }) { const [inputValue, setInputValue] = useState(""); const [isEmpty, setIsEmpty] = useState(false); - const { handleModalState } = useContext(ModalContext); - + const { isOpenModal, toggleContents } = usePortalContents(); const handleEmptyError = (e: React.FocusEvent) => { setIsEmpty(e.target.value === "" ? true : false); }; - function handleShowModal() { - handleModalState({ - isOpenModal: true, - selectURL: inputValue, - data: data, - modalType: "addToFolder", - }); - } - const handleInputValue = (e: ChangeEvent) => { setInputValue(e.target.value); }; return ( <> - + {isOpenModal && ( + + )} @@ -47,7 +43,7 @@ export function AddLinkBar({ onChange={handleInputValue} /> - + 추가하기 diff --git a/components/shared/AddLinkBar/AddLinkBarStyled.ts b/components/shared/AddLinkBar/AddLinkBarStyled.ts index 9f5b0c3059..6892e5cdc1 100644 --- a/components/shared/AddLinkBar/AddLinkBarStyled.ts +++ b/components/shared/AddLinkBar/AddLinkBarStyled.ts @@ -1,3 +1,4 @@ +import { PrimaryButton } from "@styles/common/PrimaryButton"; import styled from "styled-components"; export const AddLinkContainer = styled.div<{ isFloating: boolean }>` @@ -64,13 +65,9 @@ export const AddLinkInput = styled.input` } `; -export const AddInputButton = styled.button` - width: 8rem; +export const AddInputButton = styled(PrimaryButton)` font-size: 1.4rem; font-weight: 600; line-height: 1.671rem; - color: var(--gray-light); - background: linear-gradient(90.99deg, #6d6afe 0.12%, #6ae3fe 101.84%); padding: 1rem 1.6rem; - border-radius: 0.8rem; `; diff --git a/components/sign/signinForm/SignInForm.tsx b/components/sign/signinForm/SignInForm.tsx index ef0212c286..f6377947c2 100644 --- a/components/sign/signinForm/SignInForm.tsx +++ b/components/sign/signinForm/SignInForm.tsx @@ -25,8 +25,7 @@ export function SignForm() { }; try { - const data = await checkSignin(inputValue); - const { accessToken, refreshToken } = data; + const { accessToken, refreshToken } = await checkSignin(inputValue); router.push("/folder"); localStorage.setItem("accessToken", accessToken); localStorage.setItem("refreshToken", refreshToken); diff --git a/components/sign/signupForm/SignUpForm.tsx b/components/sign/signupForm/SignUpForm.tsx index 25702fe354..60c669f8e3 100644 --- a/components/sign/signupForm/SignUpForm.tsx +++ b/components/sign/signupForm/SignUpForm.tsx @@ -21,9 +21,9 @@ export function SignUpForm() { mode: "onBlur", }); - const isConfirmPassword = async (insertEmail: { email: string }) => { + const isConfirmPassword = async (insertEmail: string) => { try { - await checkValidationEmail(insertEmail); + await checkValidationEmail({ email: insertEmail }); return true; } catch { return "이미 사용 중인 이메일입니다."; @@ -67,7 +67,7 @@ export function SignUpForm() { message: "올바른 이메일 주소가 아닙니다.", }, validate: async (value) => { - const result = await isConfirmPassword({ email: value }); + const result = await isConfirmPassword(value); return result; }, })} diff --git a/context/UserContext.ts b/context/UserContext.ts index 18af69bce8..bace7a2392 100644 --- a/context/UserContext.ts +++ b/context/UserContext.ts @@ -3,7 +3,7 @@ import React from "react"; export interface UserContextProp { loginData: { isLogin: boolean; - userId: string; + userId: number; }; handleUserDataState: ( newState: Partial @@ -13,7 +13,7 @@ export interface UserContextProp { const InitialModalStateValue: UserContextProp = { loginData: { isLogin: false, - userId: "", + userId: 0, }, handleUserDataState: () => {}, }; diff --git a/context/UserContextProvider.tsx b/context/UserContextProvider.tsx index a244e4a638..3b2b730bff 100644 --- a/context/UserContextProvider.tsx +++ b/context/UserContextProvider.tsx @@ -4,7 +4,7 @@ import { UserContext, UserContextProp } from "./UserContext"; export function UserContextProvider({ children }: { children: ReactNode }) { const [loginData, setLoginData] = useState({ isLogin: false, - userId: "", + userId: 0, }); function handleUserDataState( diff --git a/data-access/axios/deleteFolder.ts b/data-access/axios/deleteFolder.ts new file mode 100644 index 0000000000..b4b6dade38 --- /dev/null +++ b/data-access/axios/deleteFolder.ts @@ -0,0 +1,13 @@ +import { axiosInstance } from "./axiosInstance"; + +export async function deleteFolder({ + folderId, +}: { + folderId: number | string; +}) { + const response = await axiosInstance.delete( + `/linkbrary/v1/folders/${folderId}` + ); + + return response.status; +} diff --git a/data-access/axios/deleteLink.ts b/data-access/axios/deleteLink.ts new file mode 100644 index 0000000000..733f8672f9 --- /dev/null +++ b/data-access/axios/deleteLink.ts @@ -0,0 +1,9 @@ +import { axiosInstance } from "./axiosInstance"; + +export async function deleteLink({ linkId }: { linkId: number }) { + const response = await axiosInstance.delete( + `/linkbrary/v1/folders/${linkId}` + ); + + return response.status; +} diff --git a/data-access/axios/getCategory.ts b/data-access/axios/getCategory.ts new file mode 100644 index 0000000000..070fc9b2eb --- /dev/null +++ b/data-access/axios/getCategory.ts @@ -0,0 +1,14 @@ +import { axiosInstance } from "./axiosInstance"; + +export interface FolderListDataForm { + id: number; + created_at: string; + favorite: boolean; + name: string; + link_count: number; +} + +export async function getCategory(): Promise { + const response = await axiosInstance.get(`/linkbrary/v1/folders`); + return response.data; +} diff --git a/data-access/axios/getFolderInfo.ts b/data-access/axios/getFolderInfo.ts new file mode 100644 index 0000000000..262f2adae1 --- /dev/null +++ b/data-access/axios/getFolderInfo.ts @@ -0,0 +1,19 @@ +import { axiosInstance } from "./axiosInstance"; + +interface FolderInfo { + id: number; + created_at: string; + favorite: boolean; + name: string; + user_id: number; +} + +export async function getFolderInfo({ + folderId, +}: { + folderId?: any; +}): Promise { + const response = await axiosInstance.get(`/linkbrary/v1/folders/${folderId}`); + + return response.data[0]; +} diff --git a/data-access/axios/getFolders.ts b/data-access/axios/getFolders.ts new file mode 100644 index 0000000000..99984b6a5c --- /dev/null +++ b/data-access/axios/getFolders.ts @@ -0,0 +1,23 @@ +import { axiosInstance } from "./axiosInstance"; + +export interface FolderContentsDataForm { + id: number; + favorite: boolean; + created_at: string; + url: string; + title: string; + image_source: string; + description: string; +} + +export async function getFolders({ + folderId, +}: { + folderId: number; +}): Promise { + const query = folderId ? `/folders/${folderId}` : ""; + + const response = await axiosInstance.get(`/linkbrary/v1${query}/links`); + + return response.data; +} diff --git a/data-access/axios/getUserProfile.ts b/data-access/axios/getUserProfile.ts new file mode 100644 index 0000000000..8b38971d27 --- /dev/null +++ b/data-access/axios/getUserProfile.ts @@ -0,0 +1,18 @@ +import { axiosInstance } from "./axiosInstance"; + +interface FolderOwnerProfile { + id: number; + created_at: string; + name: string; + image_source: string; + email: string; +} + +export async function getUserProfile({ + userId, +}: { + userId: any; +}): Promise { + const response = await axiosInstance.get(`/linkbrary/v1/users/${userId}`); + return response.data[0]; +} diff --git a/data-access/axios/postAddToFolder.ts b/data-access/axios/postAddToFolder.ts new file mode 100644 index 0000000000..7f8e3f9679 --- /dev/null +++ b/data-access/axios/postAddToFolder.ts @@ -0,0 +1,15 @@ +import { axiosInstance } from "./axiosInstance"; + +export async function postAddToFolder({ + url, + folderId, +}: { + url: string; + folderId: number; +}) { + const response = await axiosInstance.post(`/linkbrary/v1/links`, { + url: url, + folderId: folderId, + }); + return response.data; +} diff --git a/data-access/axios/postNewFolder.ts b/data-access/axios/postNewFolder.ts new file mode 100644 index 0000000000..b71cf13e3a --- /dev/null +++ b/data-access/axios/postNewFolder.ts @@ -0,0 +1,20 @@ +import { axiosInstance } from "./axiosInstance"; + +interface createNewFolder { + id: number; + created_at: string; + favorite: boolean; + name: string; +} + +export async function postNewFolder({ + folderName, +}: { + folderName: string; +}): Promise { + const response = await axiosInstance.post(`/linkbrary/v1/folders`, { + name: folderName, + }); + + return response.data; +} diff --git a/data-access/axios/putRenameFolder.ts b/data-access/axios/putRenameFolder.ts new file mode 100644 index 0000000000..eea04c57e7 --- /dev/null +++ b/data-access/axios/putRenameFolder.ts @@ -0,0 +1,24 @@ +import { axiosInstance } from "./axiosInstance"; + +interface PutRenameFolder { + id: number; + created_at: string; + name: string; + user_id: number; + favorite: boolean; +} + +export async function putRenameFolder({ + folderId, + folderTitle, +}: { + folderId: number; + folderTitle: string; +}): Promise { + const response = await axiosInstance.put( + `/linkbrary/v1/folders/${folderId}`, + { name: folderTitle } + ); + + return response.data; +} diff --git a/data-access/checkSignin.ts b/data-access/checkSignin.ts index 8d1cdb0dcc..55c5429a4e 100644 --- a/data-access/checkSignin.ts +++ b/data-access/checkSignin.ts @@ -1,22 +1,14 @@ -import { BASE_URL } from "./BASE_URL"; +import { axiosInstance } from "./axios/axiosInstance"; export async function checkSignin(trySignValue: { email: string; password: string; }) { - const response = await fetch(`${BASE_URL}sign-in`, { - method: "POST", - body: JSON.stringify(trySignValue), - headers: { - "Content-Type": "application/json", - }, + const response = await axiosInstance.post(`/linkbrary/v1/auth/sign-in`, { + email: trySignValue.email, + password: trySignValue.password, }); - if (!response.ok) { - throw new Error("로그인에 실패했습니다."); - } - - const { data } = await response.json(); - const { accessToken, refreshToken } = data; + const { accessToken, refreshToken } = response.data; return { accessToken, refreshToken }; } diff --git a/data-access/checkSignup.ts b/data-access/checkSignup.ts index 0ba7f78aca..23dd8bc4da 100644 --- a/data-access/checkSignup.ts +++ b/data-access/checkSignup.ts @@ -1,32 +1,21 @@ import { BASE_URL } from "./BASE_URL"; +import { axiosInstance } from "./axios/axiosInstance"; export async function checkSignup(trySignUpValue: { email: string; password: string; }) { - const response = await fetch(`${BASE_URL}sign-up`, { - method: "POST", - body: JSON.stringify(trySignUpValue), - headers: { - "Content-Type": "application/json", - }, + const response = await axiosInstance.post(`/linkbrary/v1/auth/sign-up`, { + email: trySignUpValue.email, + password: trySignUpValue.password, }); - - if (!response.ok) { - throw new Error("회원가입에 실패했습니다."); - } + return response.data; } -export async function checkValidationEmail(insertEmail: { email: string }) { - const response = await fetch(`${BASE_URL}check-email`, { - method: "POST", - body: JSON.stringify(insertEmail), - headers: { - "Content-Type": "application/json", - }, +export async function checkValidationEmail({ email }: { email: string }) { + const response = await axiosInstance.post(`/linkbrary/v1/users/check-email`, { + email: email, }); - if (!response.ok) { - throw new Error("이메일 중복 여부를 확인에 실패했습니다."); - } + return response.data; } diff --git a/data-access/getCategory.ts b/data-access/getCategory.ts deleted file mode 100644 index e98653c457..0000000000 --- a/data-access/getCategory.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { BASE_URL } from "./BASE_URL"; - -export async function getCategory() { - const response = await fetch(`${BASE_URL}users/1/folders`); - const result = await response.json(); - return result; -} diff --git a/data-access/getFolderInfo.ts b/data-access/getFolderInfo.ts index fe2851ef5d..0d5a84c05a 100644 --- a/data-access/getFolderInfo.ts +++ b/data-access/getFolderInfo.ts @@ -1,8 +1,8 @@ import { BASE_URL } from "./BASE_URL"; -export async function getFolderInfo(folderId: string | string[] | undefined) { - const response = await fetch(`${BASE_URL}folders/${folderId}`); - const result = await response.json(); +// export async function getFolderInfo(folderId: string | string[] | undefined) { +// const response = await fetch(`${BASE_URL}folders/${folderId}`); +// const result = await response.json(); - return result; -} +// return result; +// } diff --git a/data-access/getFolders.ts b/data-access/getFolders.ts deleted file mode 100644 index 9444450abd..0000000000 --- a/data-access/getFolders.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { BASE_URL } from "./BASE_URL"; - -export async function getFolders(folderId: string | string[] | undefined) { - const query = `?folderId=${folderId}`; - - const response = await fetch(`${BASE_URL}users/1/links${query}`); - const result = await response.json(); - - return result; -} diff --git a/data-access/getLoginUserInfo.ts b/data-access/getLoginUserInfo.ts index c021de15c4..fd3a5ba343 100644 --- a/data-access/getLoginUserInfo.ts +++ b/data-access/getLoginUserInfo.ts @@ -1,10 +1,14 @@ -import { GetUserInfoForm } from "../types/DataForm"; import { axiosInstance } from "./axios/axiosInstance"; -export async function getLoginUserInfo(): Promise<{ - data: GetUserInfoForm[]; -}> { - const response = await axiosInstance.get(`/users`); +interface loginUserProfile { + id: number; + name: string; + image_source: string; + email: string; +} + +export async function getLoginUserInfo(): Promise { + const response = await axiosInstance.get(`/linkbrary/v1/users`); - return response.data; + return response.data[0]; } diff --git a/data-access/getUserProfile.ts b/data-access/getUserProfile.ts index 6bbabdb956..b7014a1ce4 100644 --- a/data-access/getUserProfile.ts +++ b/data-access/getUserProfile.ts @@ -1,8 +1,8 @@ import { BASE_URL } from "./BASE_URL"; -export async function getUserProfile(userId: string) { - const response = await fetch(`${BASE_URL}users/${userId}`); - const result = response.json(); +// export async function getUserProfile(userId: string) { +// const response = await fetch(`${BASE_URL}users/${userId}`); +// const result = response.json(); - return result; -} +// return result; +// } diff --git a/hooks/usePortalContents.ts b/hooks/usePortalContents.ts new file mode 100644 index 0000000000..ea6868cd60 --- /dev/null +++ b/hooks/usePortalContents.ts @@ -0,0 +1,12 @@ +import { MouseEvent, useState } from "react"; + +export function usePortalContents() { + const [isOpenContents, setIsOpenContents] = useState(false); + + function toggleContents(event: MouseEvent) { + event.preventDefault(); + setIsOpenContents(!isOpenContents); + } + + return { isOpenModal: isOpenContents, toggleContents }; +} diff --git a/package-lock.json b/package-lock.json index 76c0f76db7..f72523edd2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,8 @@ "name": "fe-weekly-mission", "version": "0.1.0", "dependencies": { + "@tanstack/react-query": "^5.35.1", + "@tanstack/react-query-devtools": "^5.35.1", "axios": "^1.6.8", "moment": "^2.30.1", "next": "13.5.6", @@ -352,6 +354,55 @@ "tslib": "^2.4.0" } }, + "node_modules/@tanstack/query-core": { + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.35.1.tgz", + "integrity": "sha512-0Dnpybqb8+ps6WgqBnqFEC+1F/xLvUosRAq+wiGisTgolOZzqZfkE2995dEXmhuzINiTM7/a6xSGznU0NIvBkw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/query-devtools": { + "version": "5.32.1", + "resolved": "https://registry.npmjs.org/@tanstack/query-devtools/-/query-devtools-5.32.1.tgz", + "integrity": "sha512-7Xq57Ctopiy/4atpb0uNY5VRuCqRS/1fi/WBCKKX6jHMa6cCgDuV/AQuiwRXcKARbq2OkVAOrW2v4xK9nTbcCA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-query": { + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.35.1.tgz", + "integrity": "sha512-i2T7m2ffQdNqlX3pO+uMsnQ0H4a59Ens2GxtlMsRiOvdSB4SfYmHb27MnvFV8rGmtWRaa4gPli0/rpDoSS5LbQ==", + "dependencies": { + "@tanstack/query-core": "5.35.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^18.0.0" + } + }, + "node_modules/@tanstack/react-query-devtools": { + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-5.35.1.tgz", + "integrity": "sha512-G2TP8ekCo+C9IPdEswKB9mqG5pxV+DWq86lmNw/VbUpdyNwNFvKi7GdcqW1pLDi5al+zifSjGSO7QZ7zDMJcQg==", + "dependencies": { + "@tanstack/query-devtools": "5.32.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "@tanstack/react-query": "^5.35.1", + "react": "^18.0.0" + } + }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", diff --git a/package.json b/package.json index 8f7923954d..754f90ed90 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,8 @@ "lint": "next lint" }, "dependencies": { + "@tanstack/react-query": "^5.35.1", + "@tanstack/react-query-devtools": "^5.35.1", "axios": "^1.6.8", "moment": "^2.30.1", "next": "13.5.6", diff --git a/pages/_app.tsx b/pages/_app.tsx index 41e0fe71b6..66c89e5ebb 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -2,13 +2,20 @@ import { RecoilRoot } from "recoil"; import "../setting-files/global.css"; import type { AppProps } from "next/app"; import { UserContextProvider } from "context/UserContextProvider"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; + +const queryClient = new QueryClient(); export default function App({ Component, pageProps }: AppProps) { return ( - - - - - + + + + + + + + ); } diff --git a/pages/folder/[[...folderId]].tsx b/pages/folder/[[...folderId]].tsx index 0bf2c0f490..25628e9e74 100644 --- a/pages/folder/[[...folderId]].tsx +++ b/pages/folder/[[...folderId]].tsx @@ -1,45 +1,41 @@ import { useEffect, useState } from "react"; -import { FolderListDataForm } from "../../types/DataForm"; import * as S from "../../styles/pages/FolderStyled"; import { useIntersectionObserver } from "@hooks/useIntersectionObserver"; -import { getCategory } from "@data-access/getCategory"; +import { + FolderListDataForm, + getCategory, +} from "@data-access/axios/getCategory"; import FolderHeader from "@components/folder/FolderHeader"; -import { SearchBar } from "@components/common/SearchBar"; import { FolderContent } from "@components/folder/FolderContent/FolderContent"; import Footer from "@components/common/Footer"; -import { ModalProvider } from "@components/common/RefactorModal/ModalProvider"; +import { SearchBar } from "@components/common/SearchBar"; +import { useQuery } from "@tanstack/react-query"; function Folder() { - const [categoryData, setCategoryData] = useState([]); const { isVisible: isHeaderVisible, targetRef: headerRef } = useIntersectionObserver(); const { isVisible: isFooterVisible, targetRef: footerRef } = useIntersectionObserver(); + const { data } = useQuery({ + queryKey: ["folderList"], + queryFn: getCategory, + }); const floatingState = !isHeaderVisible && !isFooterVisible ? true : false; - const handleLoadCategory = async () => { - const { data } = await getCategory(); - setCategoryData(data); - }; - - useEffect(() => { - handleLoadCategory(); - }, []); - return ( - + <> - +