Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[박소현] week19 #556

Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
ed532f1
Chore: 리액트쿼리 라이브러리 설치 및 설정
ParkSohyunee Jan 12, 2024
fd9be93
Feat(Layout): 변경된 api로 유저데이터 연동
ParkSohyunee Jan 13, 2024
0179f98
Feat(FolderPage): 폴더페이지 api 변경 및 카테고리 dynamic 라우팅 추가
ParkSohyunee Jan 13, 2024
a5dc2aa
Feat(FolderPage): 선택된 폴더 페이지 추가
ParkSohyunee Jan 13, 2024
818580f
Feat(ShareContainer): 공유페이지 api 변경에 따른 로직, response 타입 수정
ParkSohyunee Jan 13, 2024
832c2b9
Feat(SignInForm): 로그인폼 api 변경
ParkSohyunee Jan 13, 2024
431cd77
Feat(SignUpForm): 회원가입폼 api 변경
ParkSohyunee Jan 13, 2024
ed85349
Refactor: 링크 검색 기능 필터링 로직 분리, 타입 추가
ParkSohyunee Jan 13, 2024
4475303
Feat(Layout): 네브바 프로필 api 연동, accessToken 여부에 따른 UI
ParkSohyunee Jan 13, 2024
753ba0f
Feat(SignUpForm): 회원가입 api 변경
ParkSohyunee Jan 14, 2024
4c02cae
Fix(SigninForm): 로그인 accessToken 로직 수정
ParkSohyunee Jan 14, 2024
aa679c2
Design(Header): 프로필 아바타 UI 수정
ParkSohyunee Jan 14, 2024
ddc9db1
Feat(AddFolders): 폴더 추가하기 기능 구현
ParkSohyunee Jan 14, 2024
fbadf32
Feat(AddLink): 링크 추가하기 기능 구현
ParkSohyunee Jan 14, 2024
f2ed2e7
Feat(DeleteFolder): 링크 삭제 기능 구현, 링크데이터 타입 수정
ParkSohyunee Jan 14, 2024
ecb98c7
Feat(DeleteFolder): 폴더 삭제 기능 구현
ParkSohyunee Jan 14, 2024
0352c15
Fix(App): SWR로 설정 변경
ParkSohyunee Jan 14, 2024
6e3c4ca
Feat(EditFolder): 폴더이름 변경 기능 구현
ParkSohyunee Jan 14, 2024
dedab35
Fix: Response types 수정, 불필요한 types 제거
ParkSohyunee Jan 14, 2024
f83202e
Style: 주석, console.log 삭제
ParkSohyunee Jan 14, 2024
cb60c95
Chore: 사용하지 않는 api 파일 삭제
ParkSohyunee Jan 14, 2024
8329902
Feat(CardItem): 카드 이미지 에러일때 UI 로직 적용
ParkSohyunee Jan 15, 2024
5bfbe18
Feat: 스토리북 실습
ParkSohyunee Jan 17, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ const nextConfig = {
protocol: "https",
hostname: "codeit-images.codeit.com",
},
{
protocol: "https",
hostname: "cloudflare-ipfs.com",
},
],
},
compiler: {
Expand Down
51 changes: 51 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
"lint": "next lint"
},
"dependencies": {
"@tanstack/react-query": "^5.17.9",
"@tanstack/react-query-devtools": "^5.17.9",
Comment on lines +14 to +15
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

react-query가 사용되지는 않는것 같은데 추가하신 이유가 있을까요?

"classnames": "^2.3.2",
"next": "13.5.6",
"react": "^18",
Expand Down
2 changes: 1 addition & 1 deletion pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import "styles/globals.css";

import type { AppProps } from "next/app";
import { FolderContextProvider } from "@/context/FolderContext";
import { SWRConfig } from "swr";
import { DOMAIN_URL } from "@/common/constants";
import { FolderContextProvider } from "@/context/SelectedFolderContext";

export default function App({ Component, pageProps }: AppProps) {
return (
Expand Down
84 changes: 26 additions & 58 deletions pages/folder/FolderContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,42 +1,34 @@
import { ChangeEvent, useContext, useEffect, useState } from "react";
import { useRouter } from "next/router";
import { ChangeEvent, useContext, useEffect, useState } from "react";

import { FolderContext } from "@/context/FolderContext";
import FolderUI from "./FolderPresenter";
import { FolderData, FolderNameData, LinkData, SharedFolderData } from "@/types/folder";
import { useFolder } from "@/hooks/useFolder";

export const DEFAULT = "전체";
// const USER_ID = 1;

/**
* @TODO
* /folders, /links api로 변경
* 토큰을 가져와서 hearder에 함께 보내기
* 다른 폴더를 선택한 경우 folder/folderId 페이지로 이동
*/
import { Folder } from "@/types/folder";
import { LinkData } from "@/types/link";
import { useFolder } from "@/hooks/useFolder";
import { FolderContext } from "@/context/SelectedFolderContext";
import { checkMatchedAllLinks } from "@/common/utils/matchedKeyword";

export default function Folder() {
const router = useRouter();
const { selectedFolderName, updateFolderName } = useContext(FolderContext);

const [links, setLinks] = useState<LinkData[]>([]);
const [filteredLinks, setFilteredLinks] = useState<LinkData[]>([]);
const [folders, setFolders] = useState<SharedFolderData[]>([]);
const [selected, setSelected] = useState(DEFAULT);
const [selectedFolderId, setSelectedFolderId] = useState("");
const [selected, setSelected] = useState(selectedFolderName);
const [addLinkValue, setAddLinkValue] = useState("");
const [keyword, setKeyword] = useState("");
const [folderNames, setFolderNames] = useState<string[]>([]);

const { data: foldersData, isLoading } = useFolder("/folders");
const { data: linksData } = useFolder("/links");

const { data: foldersData, isLoading } = useFolder("/api/folders");
const { data: linksData } = useFolder("/api/links");
console.log(foldersData); // 삭제예정
console.log(linksData); // 삭제예정
const folders: Folder[] = foldersData ?? [];
const links: LinkData[] = linksData ?? [];

const { handleFolderUpdate } = useContext(FolderContext);
const [filteredLinks, setFilteredLinks] = useState<LinkData[]>([]);

const handleOnChangeInput = (e: ChangeEvent<HTMLInputElement>) => {
setKeyword(e.target.value);
const searchedLinks = checkMatchedAllLinks(e.target.value, links);
const searchedLinks = checkMatchedAllLinks(e.target.value, linksData);
setFilteredLinks(searchedLinks.length !== 0 ? searchedLinks : []);
};

Expand All @@ -45,34 +37,13 @@ export default function Folder() {
setFilteredLinks(links);
};

const checkMatchedAllLinks = (keyword: string, links: LinkData[]) => {
const filteredLinks = links.filter((link) => {
return (
(link.title && link.title.includes(keyword)) ||
(link.description && link.description.includes(keyword)) ||
(link.url && link.url.includes(keyword))
);
});
return filteredLinks;
};

const handleSelectedFolder = (category: string) => {
setSelected(category);
changeFolderId(category);
};

const changeFolderId = (category: string) => {
const selectedFolder =
folders.find((folder: SharedFolderData) => folder.name === category)?.id ?? "";
setSelectedFolderId(selectedFolder as string);
};

const updateFolderList = (data: FolderData[]) => {
handleFolderUpdate(data);
const selectedFolderId = folders.find((folder: Folder) => folder.name === category)?.id ?? "";
updateFolderName(category);
router.push(`/folder/${selectedFolderId}`);
};

const folderNames = folders.map((folder) => folder.name);

const handleAddLink = (link: string) => {
setAddLinkValue(link);
};
Expand All @@ -85,17 +56,14 @@ export default function Folder() {
}, [router]);

useEffect(() => {
if (linksData && foldersData) {
setLinks(linksData.data.folder);
setFilteredLinks(linksData.data.folder);
setFolders(foldersData.data.folder);
// updateFolderList(foldersData.data.folder);
if (linksData) {
setFilteredLinks(linksData);
}
}, [linksData, foldersData, selectedFolderId]);

// if (linkError || folderError) {
// console.log(linkError || folderError);
// }
if (foldersData) {
const folders = foldersData.map((folder: Folder) => folder.name);
setFolderNames(folders);
}
}, [linksData, foldersData]);

return (
<FolderUI
Expand Down
7 changes: 3 additions & 4 deletions pages/folder/FolderPresenter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import Loading from "@/components/Loading";
import Options from "@/components/Options";

import { FolderUIProps } from "./FolderTypes";
import { DEFAULT } from "./FolderContainer";
import { useIntersectionObserver } from "@/hooks/useIntersectionObserver";

export default function FolderUI(props: FolderUIProps) {
Expand All @@ -26,7 +25,7 @@ export default function FolderUI(props: FolderUIProps) {
{isOpenModal && (
<ModalPortal>
<ModalContainer onClose={handleCloseModal}>
<AddFolders />
<AddFolders onClose={handleCloseModal} />
</ModalContainer>
</ModalPortal>
)}
Expand All @@ -51,7 +50,7 @@ export default function FolderUI(props: FolderUIProps) {
)}
<S.MenuContainer>
<Categories
categories={[DEFAULT, ...props.folderNames]}
categories={["전체", ...props.folderNames]}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

혹시 상수에서 이렇게 다시 바꿔주신 이유가 있을까요?

selected={props.selected}
onClick={props.handleSelectedFolder}
/>
Expand All @@ -67,7 +66,7 @@ export default function FolderUI(props: FolderUIProps) {
<>
<S.MenuContainer>
<S.SubTitle>{props.selected}</S.SubTitle>
{props.selected !== DEFAULT && <Options selected={props.selected} />}
{props.selected !== "전체" && <Options selected={props.selected} />}
</S.MenuContainer>
<CardList links={props.filteredLinks} />
</>
Expand Down
2 changes: 1 addition & 1 deletion pages/folder/FolderTypes.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { LinkData } from "@/types/link";
import { ChangeEvent } from "react";
import { LinkData } from "@/types/folder";

export interface FolderUIProps {
addLinkValue: string;
Expand Down
127 changes: 127 additions & 0 deletions pages/folder/[id]/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import { useRouter } from "next/router";
import { ChangeEvent, useContext, useEffect, useState } from "react";
import useSWR from "swr";
import * as S from "../FolderStyles";

import Layout from "@/components/layout/Layout";
import ModalPortal from "@/components/ModalPortal";
import AddFolders from "@/components/modal/AddFolders";
import ModalContainer from "@/components/modal/ModalContainer";
import FolderHero from "@/components/hero/HeroAboutFolder";
import Searchbar from "@/components/inputs/Searchbar";
import Categories from "@/components/Categories";
import CardList from "@/components/card/CardList";
import Options from "@/components/Options";
import Loading from "@/components/Loading";

import { useFolder } from "@/hooks/useFolder";
import { useIntersectionObserver } from "@/hooks/useIntersectionObserver";
import { Folder } from "@/types/folder";
import { LinkData } from "@/types/link";
import { FolderContext } from "@/context/SelectedFolderContext";
import { checkMatchedAllLinks } from "@/common/utils/matchedKeyword";

export default function FolderPage() {
const router = useRouter();
const { selectedFolderName, updateFolderName } = useContext(FolderContext);
const { ref, isIntersecting } = useIntersectionObserver<HTMLDivElement>();

const [selected, setSelected] = useState(selectedFolderName);
const [addLinkValue, setAddLinkValue] = useState("");
const [keyword, setKeyword] = useState("");
const [isOpenModal, setIsOpenModal] = useState(false);
const [filteredLinks, setFilteredLinks] = useState<LinkData[]>([]);

const { data: foldersData, isLoading } = useFolder("/folders");
const { data: linksData } = useSWR(`/folders/${router.query.id}/links`);

const folders: Folder[] = foldersData ?? [];
const links: LinkData[] = linksData ?? [];

const folderNames = folders.map((folder) => folder.name);

const handleAddLink = (link: string) => {
setAddLinkValue(link);
};

const handleCloseModal = () => setIsOpenModal(false);

const handleOnChangeInput = (e: ChangeEvent<HTMLInputElement>) => {
setKeyword(e.target.value);
const searchedLinks = checkMatchedAllLinks(e.target.value, links);
setFilteredLinks(searchedLinks.length !== 0 ? searchedLinks : []);
};

const handleDeletekeyword = () => {
setKeyword("");
setFilteredLinks(links);
};

const handleSelectedFolder = (category: string) => {
setSelected(category);
const selectedFolderId = folders.find((folder: Folder) => folder.name === category)?.id ?? "";
updateFolderName(category);
router.push(`/folder/${selectedFolderId}`);
};

useEffect(() => {
if (linksData) {
setFilteredLinks(linksData);
}
setSelected(selectedFolderName);
}, [linksData, selectedFolderName]);

return (
<>
{isOpenModal && (
<ModalPortal>
<ModalContainer onClose={handleCloseModal}>
<AddFolders onClose={handleCloseModal} />
</ModalContainer>
</ModalPortal>
)}

<Layout footerRef={ref}>
<FolderHero
onChangeAddLink={handleAddLink}
addLinkValue={addLinkValue}
isFixedInput={isIntersecting}
/>
<S.Contents>
<Searchbar
keyword={keyword}
handleOnChangeInput={handleOnChangeInput}
handleDelete={handleDeletekeyword}
/>
{keyword && (
<S.SearchInfo>
<S.SearchKeyword>{keyword}</S.SearchKeyword>
으로 검색한 결과입니다.
</S.SearchInfo>
)}
<S.MenuContainer>
<Categories
categories={["전체", ...folderNames]}
selected={selected}
onClick={handleSelectedFolder}
/>
<S.AddFolderBtn onClick={() => setIsOpenModal(true)}>
<span>폴더 추가</span>
<S.IconAdd />
</S.AddFolderBtn>
</S.MenuContainer>
{isLoading && <Loading />}
<S.MenuContainer>
<S.SubTitle>{selected}</S.SubTitle>
{selected !== "전체" && <Options selected={selected} />}
</S.MenuContainer>
{!isLoading && links.length === 0 ? (
<S.Blank>저장된 링크가 없습니다</S.Blank>
) : (
<CardList links={filteredLinks} />
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

filteredLinks를 state로 두지 않는 것이 조금 더 괜찮을 것 같습니다.

Suggested change
<CardList links={filteredLinks} />
<CardList links={checkMatchedAllLinks(keyword, links)} />

)}
</S.Contents>
</Layout>
</>
);
}
Loading