Skip to content

[김태진] week20 #1068

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

Open
wants to merge 14 commits into
base: part3-김태진
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 6 additions & 8 deletions api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,18 @@ import { Folder, FolderInfo, Link, User } from "@/types";
import { getCookie } from "@/utils/cookie";
import { instance } from "./axios";

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

export async function getUserFolderList(): Promise<{
data: { folder: Folder[] };
}> {
export async function getUserFolderList(): Promise<Folder[]> {
return (await instance.get("/folders")).data;
}

export async function getUserLinks({
folderId,
}: {
folderId: string | null;
}): Promise<{ data: { folder: Link[] } }> {
const query = folderId ? `?folderId=${folderId}` : "";
}): Promise<Link[]> {
if (!folderId) {
return (await instance.get(`/links`)).data;
}

return (await instance.get(`/links${query}`)).data;
return (await instance.get(`/folders/${folderId}/links`)).data;
}
8 changes: 4 additions & 4 deletions api/auth.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const BASE_URL = "https://bootcamp-api.codeit.kr/api";
const BASE_URL = "https://bootcamp-api.codeit.kr/api/linkbrary/v1";

export async function postUserSignin({
email,
Expand All @@ -7,7 +7,7 @@ export async function postUserSignin({
email: string;
password: string;
}) {
const response = await fetch(`${BASE_URL}/sign-in`, {
const response = await fetch(`${BASE_URL}/auth/sign-in`, {
Copy link
Collaborator

Choose a reason for hiding this comment

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

http client로 axios를 사용한다면, 특별한 경우를 제외하고는 통일하시는게 일반적으로 좋습니다

method: "POST",
body: JSON.stringify({ email, password }),
headers: {
Expand All @@ -30,7 +30,7 @@ export async function postUserSignUp({
email: string;
password: string;
}) {
const response = await fetch(`${BASE_URL}/sign-up`, {
const response = await fetch(`${BASE_URL}/auth/sign-up`, {
method: "POST",
body: JSON.stringify({ email, password }),
headers: {
Expand All @@ -47,7 +47,7 @@ export async function postUserSignUp({
}

export async function postCheckEmail({ email }: { email: string }) {
const response = await fetch(`${BASE_URL}/check-email`, {
const response = await fetch(`${BASE_URL}/users/check-email`, {
method: "POST",
body: JSON.stringify({ email }),
headers: {
Expand Down
3 changes: 1 addition & 2 deletions api/axios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ import { getCookie } from "@/utils/cookie";
import axios from "axios";

export const instance = axios.create({
baseURL: "https://bootcamp-api.codeit.kr/api",
timeout: 1000,
baseURL: " https://bootcamp-api.codeit.kr/api/linkbrary/v1",
Copy link
Collaborator

Choose a reason for hiding this comment

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

👍

});

instance.interceptors.request.use(
Expand Down
13 changes: 13 additions & 0 deletions api/folder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { instance } from "./axios";

export async function addFolder(name: string) {
return instance.post("/folders", { name });
}

export async function modifyFolder(id: string, name: string) {
return instance.put(`/folders/${id}`, { name });
}

export async function deleteFolder(id: string) {
return instance.delete(`/folders/${id}`);
}
9 changes: 9 additions & 0 deletions api/links.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { instance } from "./axios";

export async function addLink(url: string, folderId: number) {
return instance.post("/links", { url, folderId });
}

export async function deleteLink(linkId: number) {
return instance.delete(`/links/${linkId}`);
}
12 changes: 4 additions & 8 deletions api/share.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,21 @@ export async function getFolder({
folderId,
}: {
folderId: string;
}): Promise<{ data: Omit<Folder, "link">[] }> {
}): Promise<Omit<Folder, "link">[]> {
return (await instance.get(`/folders/${folderId}`)).data;
}

export async function getUser({
userId,
}: {
userId: number;
}): Promise<{ data: User[] }> {
export async function getUser({ userId }: { userId: number }): Promise<User[]> {
return (await instance.get(`/users/${userId}`)).data;
}

export async function getLinks({
userId,
folderId,
}: {
userId: string;
userId: number;
folderId: string;
}): Promise<{ data: Link[] }> {
}): Promise<Link[]> {
return (await instance.get(`/users/${userId}/links?folderId=${folderId}`))
.data;
}
3 changes: 2 additions & 1 deletion api/user.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { User } from "@/types";
import { instance } from "./axios";

export async function getUser() {
export async function getUser(): Promise<User[]> {
return (await instance.get("/users")).data;
}
29 changes: 25 additions & 4 deletions components/AddLinkModal/index.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,44 @@
import { useState } from "react";
import styles from "./styles.module.css";
import { Folder } from "../../types";
import { QueryClient, useMutation } from "@tanstack/react-query";
import { addLink } from "@/api/links";

interface Props {
folderId: string;
folders: Folder[];
linkUrl: string;
}

export const AddLinkModal = ({ folders, linkUrl }: Props) => {
export const AddLinkModal = ({ folderId, folders, linkUrl }: Props) => {
const [selectedId, setSelectedId] = useState<string | null>(null);
const queryClient = new QueryClient();
const mutation = useMutation({
mutationFn: (folder: { url: string; folderId: number }) =>
addLink(folder.url, folder.folderId),
onError: () => {
alert("링크 추가에 실패하였습니다.");
},
onSuccess: () => {
alert("링크를 성공적으로 추가했습니다.");
queryClient.invalidateQueries({ queryKey: [`links-${selectedId}`] });
},
});

const handleFolderClick = (id: string) => {
setSelectedId(id);
};

const handleAddLinks = () => {
mutation.mutate({ url: linkUrl.trim(), folderId: Number(selectedId) });
};

return (
<div className={styles.container}>
<h2 className={styles.title}>폴더에 추가</h2>
<p className={styles.description}>{linkUrl}</p>
<ul className={styles.select}>
{folders.map((folder) => (
{folders?.map((folder) => (
<li
key={folder.id}
className={`${styles.option} ${
Expand All @@ -30,13 +49,15 @@ export const AddLinkModal = ({ folders, linkUrl }: Props) => {
<div className={styles.optionContainer}>
<span className={styles.optionTitle}>{folder.name}</span>
<span className={styles.optionSubTitle}>
{folder.link.count}개 링크
{folder.link_count}개 링크
</span>
</div>
</li>
))}
</ul>
<button className={styles.btn}>추가하기</button>
<button className={styles.btn} onClick={handleAddLinks}>
추가하기
</button>
</div>
);
};
36 changes: 34 additions & 2 deletions components/AddModal/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,43 @@
import {
QueryClient,
useMutation,
useQueryClient,
} from "@tanstack/react-query";
import styles from "./styles.module.css";
import { addFolder } from "@/api/folder";
import { useState } from "react";

export const AddModal = () => {
const [name, setName] = useState("");
const queryClient = useQueryClient();

const mutation = useMutation({
mutationFn: (name: string) => addFolder(name),
onError: () => {
alert("폴더를 추가하는데 실패하였습니다.");
},
onSuccess: () => {
alert("폴더를 성공적으로 추가했습니다.");
queryClient.invalidateQueries({ queryKey: ["folders"] });
},
});

const handleAddFolder = () => {
mutation.mutate(name);
};

return (
<div className={styles.container}>
<h2 className={styles.title}>폴더 추가</h2>
<input className={styles.input} type="text" placeholder="내용 입력" />
<button className={styles.btn}>변경하기</button>
<input
className={styles.input}
onChange={(e) => setName(e.target.value)}
type="text"
placeholder="내용 입력"
/>
<button className={styles.btn} onClick={handleAddFolder}>
추가하기
</button>
</div>
);
};
37 changes: 37 additions & 0 deletions components/DeleteLinkModal/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { deleteFolder } from "@/api/folder";
import styles from "./styles.module.css";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { deleteLink } from "@/api/links";

interface Props {
linkId: number;
linkUrl: string;
}

export const DeleteLinkModal = ({ linkUrl, linkId }: Props) => {
const queryClient = useQueryClient();

const mutation = useMutation({
mutationFn: (linkId: number) => deleteLink(linkId),
onError: () => {
alert("링크를 삭제하는데 실패하였습니다.");
},
onSuccess: () => {
alert("링크를 성공적으로 삭제했습니다.");
},
});

const handleDeleteLink = () => {
mutation.mutate(linkId);
};

return (
<div className={styles.container}>
<h2 className={styles.title}>링크 삭제</h2>
<p className={styles.description}>{linkUrl}</p>
<button className={styles.btn} onClick={handleDeleteLink}>
삭제하기
</button>
</div>
);
};
24 changes: 24 additions & 0 deletions components/DeleteLinkModal/styles.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
.container {
text-align: center;
}

.title {
font-weight: bold;
font-size: 1.9rem;
margin-bottom: 10px;
}

.description {
font-size: 1.4rem;
margin-bottom: 20px;
color: #9fa6b2;
}

.btn {
width: 100%;
padding: 15px 0;
color: white;
background-color: #ff5b56;
font-size: 1.5rem;
border-radius: 10px;
}
26 changes: 24 additions & 2 deletions components/DeleteModal/index.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,38 @@
import { deleteFolder } from "@/api/folder";
import styles from "./styles.module.css";
import { useMutation, useQueryClient } from "@tanstack/react-query";

interface Props {
title: string;
description: string;
folderId: string;
}

export const DeleteModal = ({ title, description }: Props) => {
export const DeleteModal = ({ folderId, title, description }: Props) => {
const queryClient = useQueryClient();

const mutation = useMutation({
mutationFn: (folderId: string) => deleteFolder(folderId),
onError: () => {
alert("폴더를 삭제하는데 실패하였습니다.");
},
onSuccess: () => {
alert("폴더를 성공적으로 삭제했습니다.");
queryClient.invalidateQueries({ queryKey: ["folders"] });
},
});

const handleDeleteFolder = () => {
mutation.mutate(folderId);
};

return (
<div className={styles.container}>
<h2 className={styles.title}>{title}</h2>
<p className={styles.description}>{description}</p>
<button className={styles.btn}>삭제하기</button>
<button className={styles.btn} onClick={handleDeleteFolder}>
삭제하기
</button>
</div>
);
};
8 changes: 6 additions & 2 deletions components/FolderAddLinkArea/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,19 @@ import { ModalDispatchContext } from "@/context/modalContext";
interface Props {
folders: Folder[];
isFloating: boolean;
folderId: string;
}

export function FolderAddLinkArea({ folders, isFloating }: Props) {
export function FolderAddLinkArea({ folderId, folders, isFloating }: Props) {
const [linkUrl, setLinkUrl] = useState("");
const dispatch = useContext(ModalDispatchContext)!;
const handleAddLinkClick = () => {
dispatch({
type: "showModal",
payload: { modalType: "AddLinkModal", data: { folders, linkUrl } },
payload: {
modalType: "AddLinkModal",
data: { folderId, folders, linkUrl },
},
});
};

Expand Down
2 changes: 2 additions & 0 deletions components/FolderCard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ export function FolderCard({ link, folders }: Props) {
<PopOver
openPopOver={openPopOver}
handlePopOverClose={handlePopOverClose}
linkUrl={link.url}
linkId={Number(link.id)}
/>
<div className={styles.link}>
<div className={styles["link-cover"]}>
Expand Down
Loading