-
Notifications
You must be signed in to change notification settings - Fork 45
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
[유호민] Week15 #471
The head ref may contain hidden characters: "part3-\uC720\uD638\uBBFC-week15"
[유호민] Week15 #471
Changes from all commits
d8be318
426f88b
0e68764
354f802
d67b6f0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import axios from "axios"; | ||
|
||
const axiosInstance = axios.create({ | ||
baseURL: "https://bootcamp-api.codeit.kr/api", | ||
}); | ||
|
||
axiosInstance.interceptors.request.use( | ||
(config) => { | ||
const token = localStorage.getItem("accessToken"); | ||
if (token) { | ||
config.headers.Authorization = token; | ||
} | ||
return config; | ||
}, | ||
(error) => { | ||
return Promise.reject(error); | ||
} | ||
); | ||
|
||
export default axiosInstance; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,12 @@ | ||
import useUserFolders from "@/hooks/useUserFolders"; | ||
import { useEffect, useState } from "react"; | ||
import LinkCardListByFolderId from "./LinkCardListByFolderId"; | ||
import useSWR from "swr"; | ||
import { fetcher } from "@/lib/fetcher"; | ||
import axios from "axios"; | ||
import FolderButtons from "./FolderButtons"; | ||
import FolderTabs from "./FolderTabs"; | ||
import FolderTitlebar from "./FolderTitlebar"; | ||
import { useRouter } from "next/router"; | ||
import axiosInstance from "@/axios/axiosInstance"; | ||
import { fetchFolders } from "@/lib/folderFetcher"; | ||
|
||
interface UserData { | ||
id: number; | ||
|
@@ -41,8 +42,12 @@ export default function FolderMain({ | |
if (!user) { | ||
return <div>Loading...</div>; | ||
} | ||
|
||
const router = useRouter(); | ||
|
||
const [title, setTitle] = useState<string>("전체"); | ||
const [clickedButton, setClickedButton] = useState<number | null>(0); | ||
const [folders, setFolders] = useState<Folder[] | undefined | null>(); | ||
const [folderId, setFolderId] = useState<number>(0); | ||
const [filteredLinks, setFilteredLinks] = useState<Link[]>([]); | ||
const [modalStates, setModalStates] = useState<{ | ||
|
@@ -60,14 +65,13 @@ export default function FolderMain({ | |
addLinkModal: false, | ||
deleteLinkModal: false, | ||
}); | ||
|
||
const { data: folders } = useUserFolders(user.id); | ||
const { data: links } = useSWR( | ||
() => | ||
folderId === 0 | ||
? `https://bootcamp-api.codeit.kr/api/users/${user.id}/links` | ||
: `https://bootcamp-api.codeit.kr/api/users/${user.id}/links?folderId=${folderId}`, | ||
fetcher | ||
? `https://bootcamp-api.codeit.kr/api/links` | ||
: `https://bootcamp-api.codeit.kr/api/links?folderId=${folderId}`, | ||
// fetcher | ||
(url) => axiosInstance.get(url).then((res) => res.data) | ||
); | ||
|
||
const openModal = (modal: keyof typeof modalStates) => { | ||
|
@@ -78,21 +82,23 @@ export default function FolderMain({ | |
setModalStates({ ...modalStates, [modal]: false }); | ||
}; | ||
|
||
const handleButtonClick = (folderId: number) => { | ||
const handleButtonClick = (folderId: number): void => { | ||
setClickedButton(folderId); | ||
const clickedFolder = folders.data.find( | ||
const clickedFolder = folders?.find( | ||
(folder: Folder) => folder.id === folderId | ||
); | ||
if (clickedFolder) { | ||
setFolderId(clickedFolder.id); | ||
setTitle(clickedFolder.name); | ||
router.push(`/folder/${folderId}`); | ||
} | ||
}; | ||
|
||
const handleAllButtonClick = () => { | ||
setClickedButton(0); | ||
setFolderId(0); | ||
setTitle("전체"); | ||
router.push("/folder"); | ||
}; | ||
|
||
const getInputValue = async () => { | ||
|
@@ -104,7 +110,7 @@ export default function FolderMain({ | |
const handleFilter = async () => { | ||
if (links) { | ||
const i = await getInputValue(); | ||
const nextLinks = links.data.filter( | ||
const nextLinks = links?.data?.folder?.filter( | ||
(link: any) => | ||
(link.url && link.url.includes(i)) || | ||
(link.title && link.title.includes(i)) || | ||
|
@@ -119,9 +125,37 @@ export default function FolderMain({ | |
handleFilter(); | ||
}, [inputValue]); | ||
|
||
useEffect(() => { | ||
const folderIdFromURL = parseInt(router.query.folderId as string, 10) || 0; | ||
setClickedButton(folderIdFromURL); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 쿼리 값이 유니언 타입이라 as 로 타입 단언해주신 것 같아요.
이런식으로 타입 가드 함수와 커스텀 훅 작성해서 세그먼트 값과 타입 관련된 관심사를 분리할 수 있을 것 같습니다. 타입 단언 관련 글도 참고해보세요! |
||
setFolderId(folderIdFromURL); | ||
|
||
Comment on lines
+130
to
+131
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 동일한 값을 두개의 상태로 관리하시는 이유가 있을까요? |
||
if (folderIdFromURL === 0) { | ||
setTitle("전체"); | ||
} else { | ||
const clickedFolder = folders?.find( | ||
(folder: Folder) => folder.id === folderIdFromURL | ||
); | ||
setTitle(clickedFolder ? clickedFolder.name : "전체"); | ||
} | ||
}, [router.query.folderId, folders]); | ||
|
||
useEffect(() => { | ||
const fetchFoldersData = async () => { | ||
try { | ||
const { data } = await fetchFolders(); | ||
setFolders(data.folder); | ||
} catch (error) { | ||
console.error(error); | ||
} | ||
}; | ||
|
||
fetchFoldersData(); | ||
}, []); | ||
|
||
return ( | ||
<> | ||
<FolderButtons | ||
<FolderTabs | ||
clickedButton={clickedButton} | ||
handleButtonClick={handleButtonClick} | ||
handleAllButtonClick={handleAllButtonClick} | ||
|
@@ -137,7 +171,7 @@ export default function FolderMain({ | |
modalStates={modalStates} | ||
/> | ||
<LinkCardListByFolderId | ||
links={links?.data} | ||
links={links?.data?.folder} | ||
filteredLinks={filteredLinks} | ||
inputValue={inputValue} | ||
modalStates={modalStates} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,7 +8,16 @@ interface Folder { | |
favorite?: boolean; | ||
} | ||
|
||
export default function FolderButtons({ | ||
interface ModalStates { | ||
addModal: boolean; | ||
shareModal: boolean; | ||
editModal: boolean; | ||
deleteModal: boolean; | ||
addLinkModal: boolean; | ||
deleteLinkModal: boolean; | ||
} | ||
|
||
export default function FolderTabs({ | ||
clickedButton, | ||
handleButtonClick, | ||
handleAllButtonClick, | ||
|
@@ -17,13 +26,13 @@ export default function FolderButtons({ | |
closeModal, | ||
modalStates, | ||
}: { | ||
clickedButton: any; | ||
handleButtonClick: any; | ||
handleAllButtonClick: any; | ||
folders: any; | ||
openModal: any; | ||
closeModal: any; | ||
modalStates: any; | ||
clickedButton: number | null; | ||
handleButtonClick: (folderId: number) => void; | ||
handleAllButtonClick: () => void; | ||
Comment on lines
+30
to
+31
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 함수 props 네이밍 관련된 자료입니당 참고해보시면 좋을 것 같아요 |
||
folders: Folder[] | undefined | null; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. folders 타입으로 세가지를 가지고 있는데 각각 값에 따라서 다른 처리를 해야하나용? 그게 아니라면
요렇게 세가지 중에 folders 값에 따라서 처리하는게 어떻게 달라지는지를 생각하고 타입을 명시해주시면 더 명확한 인터페이스가 될 것 같아요! |
||
openModal: (modal: keyof ModalStates) => void; | ||
closeModal: (modal: keyof ModalStates) => void; | ||
modalStates: ModalStates; | ||
}) { | ||
return ( | ||
<div className="flex items-center justify-between mt-[40px] px-[32px] xl:px-[200px]"> | ||
|
@@ -39,7 +48,7 @@ export default function FolderButtons({ | |
전체 | ||
</button> | ||
{folders && | ||
folders.data.map((folder: Folder) => { | ||
folders?.map((folder: Folder) => { | ||
return ( | ||
<button | ||
key={folder.id} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ import { calculateTimeDiff } from "@/utils/calculateTimeDiff"; | |
import { useState } from "react"; | ||
import Modal from "./Modal"; | ||
import { formatDate } from "@/utils/formatDate"; | ||
import Link from "next/link"; | ||
|
||
interface Link { | ||
id: string; | ||
|
@@ -29,15 +30,17 @@ export default function LinkCardByFolderId({ | |
setShowPopover(!showPopover); | ||
}; | ||
|
||
console.log(link); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 로그 지워주세용 |
||
|
||
return ( | ||
<div className="w-[300px] h-[300px] m-[50px] shadow-2xl"> | ||
<a href={link.url} target="_blank" rel="noreferrer"> | ||
<Link href={`https://${link.url}`} target="_blank" rel="noreferrer"> | ||
<img | ||
src={link.image_source ? link.image_source : "/images/no-image.svg"} | ||
alt="link" | ||
className="w-[350px] h-[200px] object-cover rounded-md" | ||
/> | ||
</a> | ||
</Link> | ||
<div className="px-5 py-4"> | ||
<div className="relative flex justify-between"> | ||
<p className="text-[#666] text-[13px]"> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
인터셉터로 헤더에 토큰 값 넣어주신 부분도 좋습니다~
스토리지 키값은 상수로 관리해서 일괄적으로 사용하면 더 좋을 것 같아요