Skip to content

Commit 4fdba55

Browse files
authored
Merge branch 'develop' into feature/folderShare
2 parents 88da1b7 + 22e3246 commit 4fdba55

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+533
-265
lines changed

components/Folder/AddFolderButton.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,24 @@ import useRerenderFolderList from "@/hooks/useRerenderFolderList";
44

55
interface AddFolderButtonProps {
66
setFolderList: React.Dispatch<React.SetStateAction<FolderData[]>>;
7+
isModal?: boolean;
78
}
89

9-
export const AddFolderButton = ({ setFolderList }: AddFolderButtonProps) => {
10+
export const AddFolderButton = ({
11+
setFolderList,
12+
isModal = false,
13+
}: AddFolderButtonProps) => {
1014
const { isOpen, openModal } = useModalStore();
1115

1216
useRerenderFolderList(isOpen, setFolderList);
1317

1418
return (
1519
<button
16-
className="w-[79px] h-[19px] text-purple100"
20+
className={
21+
!isModal
22+
? "w-[100px] mt-auto text-purple100"
23+
: "fixed-bottom w-[120px] h-[35px] rounded-[20px] bg-purple100 text-white hover:bg-purple50"
24+
}
1725
onClick={() => openModal("AddFolderModal")}
1826
>
1927
폴더 추가 +

components/Folder/FolderActionsMenu.tsx

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,15 @@ import useRerenderFolderList from "../../hooks/useRerenderFolderList";
55

66
interface FolderActionsMenuProps {
77
setFolderList: React.Dispatch<React.SetStateAction<FolderData[]>>;
8+
folderId: string | string[] | undefined;
9+
linkCount: number;
810
}
911

10-
const FolderActionsMenu = ({ setFolderList }: FolderActionsMenuProps) => {
12+
const FolderActionsMenu = ({
13+
setFolderList,
14+
folderId,
15+
linkCount,
16+
}: FolderActionsMenuProps) => {
1117
const { isOpen, openModal } = useModalStore();
1218

1319
const handleModalOpen = (text: string) => {
@@ -16,10 +22,15 @@ const FolderActionsMenu = ({ setFolderList }: FolderActionsMenuProps) => {
1622
openModal("SNSModal");
1723
break;
1824
case "이름 변경":
19-
openModal("EditModal");
25+
openModal("EditModal", {
26+
folderId: Number(folderId),
27+
});
2028
break;
2129
case "삭제":
22-
openModal("DeleteFolderModal");
30+
openModal("DeleteFolderModal", {
31+
folderId: Number(folderId),
32+
linkCount: linkCount,
33+
});
2334
break;
2435
default:
2536
break;

components/Folder/FolderTag.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,23 @@ const FolderTag = ({ folderList }: FolderListData) => {
66
const { folder: currentFolderId } = router.query;
77

88
const folderStyle =
9-
"py-[8px] px-[12px] border border-purple100 rounded-md hover:bg-purple100 hover:text-white";
9+
"w-[100px] h-[35px] px-[15px] text-sm whitespace-nowrap truncate border border-purple100 rounded-md hover:bg-purple100 hover:text-white";
1010

11-
const handleSubmit = (id: number | string) => {
11+
const handleSubmit = (selectedFolderId: number | string) => {
1212
router.push({
1313
pathname: router.pathname,
14-
query: id ? { folder: id } : {},
14+
query: selectedFolderId ? { folder: selectedFolderId } : {},
1515
});
1616
};
1717

1818
return (
19-
<ul className="flex flex-wrap gap-[8px]">
19+
<ul className="flex flex-wrap gap-[8px] lg:w-[80%] md:w-[80%]">
2020
<li>
2121
<button className={folderStyle} onClick={() => handleSubmit("")}>
2222
전체
2323
</button>
2424
</li>
25-
{folderList.map((folder) => (
25+
{folderList.slice(0, 8).map((folder) => (
2626
<li key={folder.id}>
2727
<button
2828
className={`${folderStyle} ${folder.id === Number(currentFolderId) && "bg-purple100 text-white"}`}

components/HeaderMenu.tsx

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,23 @@ import Link from "next/link";
55
import SubmitButton from "./SubMitButton";
66
import { useRouter } from "next/router";
77
import useAuthStore from "@/store/useAuthStore";
8-
import { useEffect, useState } from "react";
8+
import { useEffect, useRef, useState } from "react";
99
import Dropdown from "./Dropdown";
10+
import useOutsideClick from "@/hooks/useOutsideClick";
1011

1112
const HeaderMenu = () => {
12-
const { user, checkLogin, isLoggedIn, logout } = useAuthStore();
13+
const { user, logout, fetchUserInfo } = useAuthStore();
1314
const [isOpen, setIsOpen] = useState(false);
1415
const router = useRouter();
16+
const dropdownRef = useRef<HTMLDivElement | null>(null);
17+
18+
useOutsideClick(dropdownRef, () => {
19+
setIsOpen(false);
20+
});
1521

1622
useEffect(() => {
17-
checkLogin();
18-
}, [checkLogin]);
23+
fetchUserInfo();
24+
}, [fetchUserInfo]);
1925

2026
const dropdownItems = [
2127
{
@@ -31,7 +37,7 @@ const HeaderMenu = () => {
3137

3238
return (
3339
<>
34-
{!isLoggedIn ? (
40+
{!user ? (
3541
<SubmitButton
3642
onClick={() => {
3743
router.push("/login");
@@ -61,6 +67,7 @@ const HeaderMenu = () => {
6167
<div
6268
className="flex items-center gap-[6px] text-[14px] leading-[16.71px] font-normal cursor-pointer"
6369
onClick={() => setIsOpen(!isOpen)}
70+
ref={dropdownRef}
6471
>
6572
<Image src={Profile} width={28} height={28} alt="프로필" />
6673
<span className="hidden md:block lg:block">{user?.name}</span>

components/Layout/CardsLayout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ interface CardsLayoutProps {
66

77
const CardsLayout = ({ children }: CardsLayoutProps) => {
88
return (
9-
<div className="grid place-items-center grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-5 md:gap-6 lg:gap-[20px] w-full">
9+
<div className="flex flex-wrap items-center gap-5 md:gap-6 lg:gap-[20px] w-full">
1010
{children}
1111
</div>
1212
);

components/Layout/Container.tsx

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,32 @@
1-
import React from "react";
1+
import React, { useEffect, useState } from "react";
2+
import ToTopBtn from "@/components/toTopBtn/ToTopBtn";
23

34
interface ContainerProps {
45
children: React.ReactNode;
56
}
67

78
const Container = ({ children }: ContainerProps) => {
9+
const [showBtn, setShowBtn] = useState(false);
10+
11+
useEffect(() => {
12+
const handleScroll = () => {
13+
if (window.scrollY > 300) {
14+
setShowBtn(true);
15+
} else {
16+
setShowBtn(false);
17+
}
18+
};
19+
window.addEventListener("scroll", handleScroll);
20+
21+
return () => {
22+
window.removeEventListener("scroll", handleScroll);
23+
};
24+
}, []);
25+
826
return (
9-
<div className="w-full max-w-[1125px] mx-auto p-[10px] md:p-10 lg:p-10 px-[32.5px]">
27+
<div className="w-full lg:max-w-[1060px] md:max-w-[704px] sm:max-w-[325px] mx-auto">
1028
{children}
29+
{showBtn && <ToTopBtn />}
1130
</div>
1231
);
1332
};

components/Layout/Footer.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import SocialLinks from "../SocialLinks";
33

44
const Footer = () => {
55
return (
6-
<footer className="bg-black200 pt-8 sm:px-8 pb-[108px] md:px-[104px] lg:px-[104px]">
7-
<nav className="relative flex justify-between">
6+
<footer className="bg-black200 pt-8 sm:px-8 pb-[108px] md:px-[104px] lg:px-[104px] flex justify-center">
7+
<nav className="relative w-full lg:max-w-[1520px] md:max-w-[800px] sm:max-w-[326px] flex justify-between">
88
<p className="text-gray700 sm:absolute sm:top-[60px] leading-[18.4px]">
99
©codeit - 2023
1010
</p>

components/Layout/Header.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import HeaderMenu from "../HeaderMenu";
55

66
const Header = () => {
77
return (
8-
<header className="bg-gray100 py-[13px] px-[32px] md:py-[33px] md:px-[200px] lg:py-[33px] lg:px-[200px]">
9-
<div className="flex justify-between items-center max-w-[1520px]">
8+
<header className="bg-gray100 py-[13px] px-[30px] flex justify-center">
9+
<div className="flex justify-between items-center w-full lg:max-w-[1520px] md:max-w-[800px] sm:max-w-[326px]">
1010
<h1 className="w-[88.67px] h-[16px] md:w-[133px] md:h-[24px] lg:w-[133px] lg:h-[24px]">
1111
<Link href={"/"}>
1212
<Image src={Logo} width={133} height={24} alt="로고" />

components/Link/AddLinkInput.tsx

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,18 +35,22 @@ const AddLinkInput = ({ folderList }: FolderListData) => {
3535
};
3636

3737
return (
38-
<div className="flex bg-white gap-[12px] items-center w-[800px] h-[69px] py-[16px] px-[20px] border border-blue-500 rounded-[10px] md:w-[704px] sm:w-[325px] sm:h-[53px] transition-all">
38+
<div className="flex bg-white justify-between items-center w-full lg:max-w-[800px] md:max-w-[704px] sm:max-w-[325px] h-[69px] lg:px-5 md:px-5 sm:px-[10px] border border-blue-500 rounded-[10px] md:w-[704px] sm:w-[325px] sm:h-[53px] transition-all">
3939
<Image src="/icons/link.svg" width={20} height={20} alt="link icon" />
4040
<input
4141
onChange={handleChange}
4242
onKeyDown={handleKeyDown}
4343
value={link}
4444
placeholder="링크를 추가해 보세요."
45-
className="flex-grow"
45+
className="lg:ml-3 md:ml-3 sm:ml-[8px]"
4646
/>
47-
<div onClick={handleClick}>
48-
<SubmitButton className="w-[80px] h-[37px]">추가하기</SubmitButton>
49-
</div>
47+
<SubmitButton
48+
onClick={handleClick}
49+
className="w-[80px] h-[37px] text-[14px]"
50+
>
51+
추가하기
52+
</SubmitButton>
53+
5054
{isOpen && <Modal />}
5155
</div>
5256
);

components/Link/LinkCard.tsx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import { useEffect, useState } from "react";
1+
import { useEffect, useRef, useState } from "react";
22
import { useRouter } from "next/router";
3-
import { putLinkFavorite } from "@/lib/api/link";
43
import { useLinkCardStore } from "@/store/useLinkCardStore";
54
import { ensureAbsoluteUrl } from "@/lib/utils";
6-
import timeAgo from "@/util/timAgo";
5+
import timeAgo from "@/util/timeAgo";
76
import Image from "next/image";
87
import Dropdown from "../Dropdown";
98
import useModalStore from "@/store/useModalStore";
9+
import useOutsideClick from "@/hooks/useOutsideClick";
1010

1111
interface LinkCardProps {
1212
info: {
@@ -24,24 +24,29 @@ const LinkCard = ({ info }: LinkCardProps) => {
2424
const [isSubscribed, setIsSubscribed] = useState(info.favorite || false);
2525
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
2626
const { isOpen, openModal } = useModalStore();
27+
2728
const { updateFavorite } = useLinkCardStore();
2829

2930
const formattedDate = info.createdAt?.slice(0, 10).replace(/-/g, ".");
3031
const createdTime = timeAgo(info.createdAt);
3132

3233
const router = useRouter();
3334
const isFavoritePage = router.pathname === "/favorite";
35+
const dropdownRef = useRef<HTMLDivElement | null>(null);
3436

3537
// 모달이 열릴 때 드롭다운 닫기
3638
useEffect(() => {
3739
if (isOpen) setIsDropdownOpen(false);
3840
}, [isOpen]);
3941

42+
useOutsideClick(dropdownRef, () => {
43+
setIsDropdownOpen(false);
44+
});
45+
4046
// 즐겨찾기 버튼 클릭 시 호출되는 함수
4147
const handleFavoriteToggle = async () => {
4248
setIsSubscribed((prev) => !prev);
4349
try {
44-
await putLinkFavorite(info.id, { favorite: !isSubscribed });
4550
updateFavorite(info.id, !isSubscribed);
4651
} catch (error) {
4752
console.error("즐겨찾기 설정 중 오류 발생:", error);
@@ -104,7 +109,7 @@ const LinkCard = ({ info }: LinkCardProps) => {
104109
</span>
105110
{/* isFavoritePage일 때만 케밥 버튼 렌더링 */}
106111
{!isFavoritePage && (
107-
<div className="relative">
112+
<div className="relative" ref={dropdownRef}>
108113
<button
109114
className="relative w-[21px] h-[17px]"
110115
onClick={toggleDropdown}

0 commit comments

Comments
 (0)