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

[이정윤] week20 #561

Merged
14 changes: 7 additions & 7 deletions types/folder.d.ts → @types/folder.types.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
// sample folder
interface Folder {
export interface Folder {
folder: FolderData;
}

interface FolderData {
export interface FolderData {
id: number;
name: string;
owner: Owner;
links: FolderLinks[];
count: number;
}

interface Owner {
export interface Owner {
id: number;
name: string;
profileImageSource: string;
}

interface FolderLinks {
export interface FolderLinks {
id?: number;
createdAt: string;
url: string;
Expand All @@ -27,19 +27,19 @@ interface FolderLinks {
}

// user folder
interface UserFolderData {
export interface UserFolderData {
data: UserFolder[];
}

interface UserFolders {
export interface UserFolders {
created_at: string;
favorite: boolean;
Copy link
Collaborator

Choose a reason for hiding this comment

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

boolean 타입이기 때문에 isFavorite 같은 변수명도 괜찮을 것 같습니다. 혹시 api 명세서에 나온 내용이라면 그냥 냅두셔도 좋습니다.

id: number;
link_count: number;
name: string;
}

interface UserFolder {
export interface UserFolder {
id: number;
created_at: string;
favorite: boolean;
Expand Down
7 changes: 4 additions & 3 deletions types/link.d.ts → @types/link.types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
interface LinksData {
export interface LinksData {
data: Link[];
}
interface Link {
export interface Link {
id: number;
created_at: string;
updated_at: null;
Copy link
Collaborator

Choose a reason for hiding this comment

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

updated_at이 무조건 null이라면 굳이 타입으로 지정하지 않으셔도 됩니다.

Expand All @@ -12,8 +12,9 @@ interface Link {
folder_id: number;
}

interface FolderLink {
export interface FolderLink {
id: number;
favorite: boolean;
created_at: string;
url: string;
title: string;
Expand Down
6 changes: 3 additions & 3 deletions types/user.d.ts → @types/user.types.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
interface SampleUser {
export interface SampleUser {
id: number;
name: string;
email: string;
profileImageSource: string;
}

interface UserData {
export interface UserData {
data: User[];
}

interface User {
export interface User {
id: number;
created_at: string;
name: string;
Expand Down
File renamed without changes
10 changes: 10 additions & 0 deletions assets/images/star-on.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions components/AddLink/AddLinkButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import ModalContainer from "../Modal/ModalContainer/ModalContainer";
import useModal from "@/hooks/useModal";
import AddLinkModalContent from "../Modal/AddLinkModalContent/AddLinkModalContent";
import isValidURL from "@/utils/isValidURL";
import { UserFolders } from "@/@types/folder.types";

interface Props {
inputValue: string;
Expand Down
1 change: 1 addition & 0 deletions components/AddLink/AddLinkInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import Image from "next/image";
import classNames from "classnames";
import isValidURL from "@/utils/isValidURL";
import AddLinkButton from "./AddLinkButton";
import { UserFolders } from "@/@types/folder.types";

interface Props {
folderData?: UserFolders[];
Expand Down
48 changes: 48 additions & 0 deletions components/Card/CardFavoriteButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import Image from "next/image";

import styles from "./CardItem.module.css";

import starOnImg from "@/assets/images/star-on.svg";
import starOffImg from "@/assets/images/star-off.svg";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import fetcher from "@/lib/axios";
import { UserFolders } from "@/@types/folder.types";

interface FolderPageCardItemProps {
isFavorite: boolean;
linkId: number;
}

function CardFavoriteButton({ isFavorite, linkId }: FolderPageCardItemProps) {
const queryClient = useQueryClient();

const toggleFavoriteMutation = useMutation({
mutationFn: async () => {
const response = await fetcher<UserFolders[]>({
url: `/links/${linkId}`,
method: "put",
data: { favorite: !isFavorite },
});
return response.data;
},
Comment on lines +20 to +27
Copy link
Collaborator

Choose a reason for hiding this comment

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

api 요청하는 함수는 따로 작성해서 파일로 관리하셔도 좋습니다.

onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["links"] });
queryClient.invalidateQueries({ queryKey: ["links", "all"] });
},
onError: (error) => {
const errorResponse = (error as any).response;
window.alert(errorResponse?.data.message);
},
});

const handleButtonClick = () => {
toggleFavoriteMutation.mutate();
};
return (
<button className={styles.bookmarkButton} onClick={handleButtonClick}>
<Image src={isFavorite ? starOnImg : starOffImg} alt="즐겨찾기 이미지" />
Copy link
Collaborator

Choose a reason for hiding this comment

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

next/Image 사용하실때 크기 지정도 해주셔야합니다!

</button>
);
}

export default CardFavoriteButton;
13 changes: 12 additions & 1 deletion components/Card/CardList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { ReactNode } from "react";
import FolderPageCardItem from "./FolderPageCardItem";
import { formatDate, getTimeDiff, prettyFormatTimeDiff } from "@/utils/utils";
import SharedPageCardItem from "./SharedPageCardItem";
import { FolderLink } from "@/@types/link.types";
import { UserFolders } from "@/@types/folder.types";

interface CardListProps {
type: "folder" | "shared";
Expand All @@ -17,7 +19,15 @@ function CardList({
return (
LinksData &&
Copy link
Collaborator

Choose a reason for hiding this comment

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

카멜케이스로 작성해주시면 좋을 것 같고, folderListData 처럼 linksData?: FolderLink[]로 작성해주셔도 좋을 것 같습니다.

LinksData.map((link) => {
const { id, created_at, url, title, description, image_source } = link;
const {
id,
created_at,
url,
title,
description,
image_source,
favorite,
} = link;

const formattedCreatedAt = formatDate(created_at);
const timeDiff = getTimeDiff(created_at);
Expand All @@ -28,6 +38,7 @@ function CardList({
<FolderPageCardItem
key={url}
id={id}
favorite={favorite}
folderListData={folderListData}
formatTimeDiff={formatTimeDiff}
formattedCreatedAt={formattedCreatedAt}
Expand Down
9 changes: 5 additions & 4 deletions components/Card/FolderPageCardItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ import CardMenu from "@/components/CardMenu/CardMenu";
import { blurDataURL } from "@/utils/utils";

import logoImg from "@/assets/images/emptyImg.svg";
import starImg from "@/assets/images/star.svg";

import styles from "./CardItem.module.css";
import CardFavoriteButton from "./CardFavoriteButton";
import { UserFolders } from "@/@types/folder.types";

interface FolderPageCardItemProps {
id: number;
favorite: boolean;
folderListData: UserFolders[];
formatTimeDiff: string;
formattedCreatedAt: string;
Expand All @@ -23,6 +25,7 @@ interface FolderPageCardItemProps {

function FolderPageCardItem({
id,
favorite,
folderListData,
formatTimeDiff,
formattedCreatedAt,
Expand All @@ -48,9 +51,7 @@ function FolderPageCardItem({
blurDataURL={blurDataURL}
/>
</Link>
<button className={styles.bookmarkButton}>
<Image src={starImg} alt="즐겨찾기 이미지" />
</button>
<CardFavoriteButton isFavorite={favorite} linkId={id} />
<div className={styles.contentContainer}>
<div className={styles.container}>
<p className={styles.timeDiff}>{formatTimeDiff}</p>
Expand Down
1 change: 1 addition & 0 deletions components/CardMenu/CardMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import ModalContainer from "@/components/Modal/ModalContainer/ModalContainer";
import kebabImg from "@/assets/images/kebab.svg";

import styles from "./CardMenu.module.css";
import { UserFolders } from "@/@types/folder.types";

interface Props {
linkId: number;
Expand Down
1 change: 1 addition & 0 deletions components/Category/CategoryList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ReactNode, Dispatch, SetStateAction } from "react";
import styles from "./CategoryList.module.css";

import CategoryButton from "./CategoryButton";
import { UserFolders } from "@/@types/folder.types";

interface Props {
folderListData?: UserFolders[];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import ModalTitle from "../ModalTitle/ModalTitle";
import { useState } from "react";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import fetcher from "@/lib/axios";
import { UserFolders } from "@/@types/folder.types";

interface Props {
onClose: () => void;
Expand Down
38 changes: 22 additions & 16 deletions components/Modal/AddLinkModalContent/AddLinkModalContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import ModalButton from "../ModalButton/ModalButton";
import Image from "next/image";
import fetcher from "@/lib/axios";
import { useSetFolderId } from "@/contexts/UserContext";
import { UserFolders } from "@/@types/folder.types";

interface Props {
inputValue: string;
Expand Down Expand Up @@ -74,23 +75,28 @@ function AddLinkModalContent({ inputValue, folderListData, onClose }: Props) {
<p className={styles.link}>{inputValue}</p>
</div>
<div className={styles.optionsContainer}>
{folderListDataArray?.map((folder) => (
<div
className={classNames(
styles.optionContainer,
selectedFolder === folder && styles.selected
)}
key={folder.id}
id={folder.name}
onClick={() => handleCheckClick(folder)}
>
<div className={styles.option}>
<h2>{folder.name}</h2>
<p>{`${folder?.link_count}개 링크`}</p>
{folderListDataArray?.map((folder) => {
if (folder.name === "⭐️ 즐겨찾기") return;
Copy link
Collaborator

Choose a reason for hiding this comment

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

폴더명을 검사하는 로직은 조금 위험해보이긴 합니다. 어쩔 수 없는 경우라면 폴더명을 상수로 관리하시면 좋을 것 같습니다.

return (
<div
className={classNames(
styles.optionContainer,
selectedFolder === folder && styles.selected
)}
key={folder.id}
id={folder.name}
onClick={() => handleCheckClick(folder)}
>
<div className={styles.option}>
<h2>{folder.name}</h2>
<p>{`${folder?.link_count}개 링크`}</p>
Comment on lines +91 to +92
Copy link
Collaborator

Choose a reason for hiding this comment

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

위에는 folder.name이고 아래는 folder?.link_count 인데, folder가 nullable 하다면 둘다 ?를 붙여주시는게 좋아보입니다.

</div>
{selectedFolder === folder && (
<Image src={checkImg} alt="check" />
)}
</div>
{selectedFolder === folder && <Image src={checkImg} alt="check" />}
</div>
))}
);
})}
</div>
<ModalButton color="blue" onClick={handleAddLink}>
추가하기
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { useMutation, useQueryClient } from "@tanstack/react-query";
import fetcher from "@/lib/axios";
import { useFolderId, useSetFolderId } from "@/contexts/UserContext";
import { useRouter } from "next/router";
import { UserFolders } from "@/@types/folder.types";

interface Props {
onClose: () => void;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import ModalButton from "../ModalButton/ModalButton";
import ModalTitle from "../ModalTitle/ModalTitle";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import fetcher from "@/lib/axios";
import { UserFolders } from "@/@types/folder.types";

interface Props {
linkId: number;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import ModalTitle from "../ModalTitle/ModalTitle";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import fetcher from "@/lib/axios";
import { useFolderId } from "@/contexts/UserContext";
import { UserFolders } from "@/@types/folder.types";

interface Props {
currentFolderName: string;
Expand Down
2 changes: 1 addition & 1 deletion components/NavBar/LoginButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ function LoginButton() {
};
const handleLogout = () => {
removeTokens();
router.push("/");
window.location.href = "/";
};

useEffect(() => {
Expand Down
1 change: 1 addition & 0 deletions components/Search/Search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
} from "react";

import SearchBar from "./SearchBar";
import { FolderLink } from "@/@types/link.types";

interface Props {
linksListData?: FolderLink[];
Expand Down
4 changes: 3 additions & 1 deletion constants/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ const PW_FIELD_INFO = {

const BASE_URL = "https://bootcamp-api.codeit.kr/api/linkbrary/v1";

export { EMAIL_FIELD_INFO, PW_FIELD_INFO, BASE_URL };
const ENDPOINT_REFRESH_TOKEN = "auth/refresh-token";

export { EMAIL_FIELD_INFO, PW_FIELD_INFO, BASE_URL, ENDPOINT_REFRESH_TOKEN };
2 changes: 1 addition & 1 deletion contexts/AuthContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ const AuthProvider = ({ children }: { children: ReactNode }) => {
method: "post",
data: { email, password },
});
console.log(response.data);
const { accessToken, refreshToken } = response.data;

saveTokens({ accessToken, refreshToken });
getUser();
return true;
Expand Down
Empty file removed hooks/useValidate.ts
Empty file.
Loading