Skip to content

Commit de86de1

Browse files
authored
Refactor: 폴더 삭제 시 url /link 로 이동 / SearchInput debounce 적용
Refactor: 폴더 삭제 시 url /link 로 이동 / SearchInput debounce 적용
2 parents 68871a2 + 7921504 commit de86de1

File tree

10 files changed

+59
-21
lines changed

10 files changed

+59
-21
lines changed

components/Folder/AddFolderButton.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export const AddFolderButton = ({
1919
<button
2020
className={
2121
!isModal
22-
? "w-[100px] mt-auto text-purple100"
22+
? "md:mt-auto xl:mt-0 text-purple100"
2323
: "fixed-bottom w-[120px] h-[35px] rounded-[20px] bg-purple100 text-white hover:bg-purple50"
2424
}
2525
onClick={() => openModal("AddFolderModal")}

components/Search/SearchInput.tsx

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,36 @@
1-
import { ChangeEvent, FormEvent, useState } from "react";
1+
import { ChangeEvent, useEffect, useState } from "react";
22
import { useRouter } from "next/router";
33
import Image from "next/image";
4+
import useDebounce from "@/hooks/useDebounce";
45

56
export const SearchInput = () => {
67
const router = useRouter();
78
const [value, setValue] = useState("");
89

10+
const debouncedValue = useDebounce(value, 200);
11+
912
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
13+
e.preventDefault();
1014
setValue(e.target.value);
1115
};
1216

13-
const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
14-
e.preventDefault();
15-
router.push({
16-
pathname: router.pathname,
17-
query: { ...router.query, search: value },
18-
});
17+
useEffect(() => {
18+
if (debouncedValue) {
19+
router.push({
20+
pathname: router.pathname,
21+
query: { ...router.query, search: debouncedValue },
22+
});
23+
}
24+
}, [debouncedValue]);
25+
26+
const handleClick = () => {
1927
setValue("");
28+
router.push("/link");
2029
};
2130

2231
return (
2332
<form
24-
onSubmit={handleSubmit}
33+
onSubmit={(e) => e.preventDefault()}
2534
className="flex gap-[8px] w-full h-[54px] items-center px-[16px] py-[15px] bg-gray-100 rounded-[10px] md:h-[54px] sm:h-[43px] transition-all"
2635
>
2736
<Image
@@ -36,6 +45,15 @@ export const SearchInput = () => {
3645
placeholder="링크를 검색해 보세요."
3746
className="flex-grow bg-transparent placeholder:text-gray-500"
3847
/>
48+
{value && (
49+
<button
50+
className="rounded-full bg-white size-6 font-bold text-gray-500 flex items-center justify-center"
51+
type="button"
52+
onClick={handleClick}
53+
>
54+
×
55+
</button>
56+
)}
3957
</form>
4058
);
4159
};

components/modal/AddModal.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { useRouter } from "next/router";
1212
const AddModal = ({ list, link }: { list: FolderItemType[]; link: string }) => {
1313
const [selectedId, setSelectedId] = useState<number | null>(null);
1414
const { closeModal } = useModalStore();
15-
const route = useRouter();
15+
const router = useRouter();
1616

1717
const handleSubmit = async () => {
1818
const body = {
@@ -25,7 +25,7 @@ const AddModal = ({ list, link }: { list: FolderItemType[]; link: string }) => {
2525
try {
2626
await postLink(body);
2727
toast.success(toastMessages.success.addLink);
28-
route.push(`/link?folder=${selectedId}`);
28+
router.push(`/link?folder=${selectedId}`);
2929
} catch (error) {
3030
toast.error(toastMessages.error.addLink);
3131
} finally {

components/modal/DeleteFolderModal.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import SubmitButton from "../SubMitButton";
44
import ModalContainer from "./modalComponents/ModalContainer";
55
import toast from "react-hot-toast";
66
import toastMessages from "@/lib/toastMessage";
7+
import { useRouter } from "next/router";
78

89
const DeleteFolderModal = ({
910
// folderName,
@@ -15,16 +16,17 @@ const DeleteFolderModal = ({
1516
linkCount: number;
1617
}) => {
1718
const { closeModal } = useModalStore();
19+
const router = useRouter();
1820
const handleSubmit = async () => {
1921
// 폴더 내에 링크 개수 0 일때만 폴더 삭제 가능 -> 링크 1개 이상이면 error toast 띄우고 있음 or 전체 링크 삭제 후 폴더 삭제
20-
2122
if (linkCount !== 0) {
2223
toast.error(toastMessages.error.deleteNonEmptyFolder);
2324
closeModal();
2425
} else {
2526
try {
2627
await deleteFolder(folderId);
2728
toast.success(toastMessages.success.deleteFolder);
29+
router.push("/link");
2830
} catch (error) {
2931
toast.error(toastMessages.error.deleteFolder);
3032
} finally {

components/modal/modalComponents/FolderItemRadio.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { bindCls } from "@/lib/utils";
21
import { FolderItemType } from "@/types/modalTypes";
2+
import { bindClass } from "@/util/bindClass";
33
import { FaCheck } from "react-icons/fa6";
44

55
const FolderItemRadio = ({
@@ -20,7 +20,7 @@ const FolderItemRadio = ({
2020
};
2121
return (
2222
<li
23-
className={bindCls(
23+
className={bindClass(
2424
bgColor,
2525
"w-full p-2 flex h-10 rounded-lg items-center justify-between cursor-pointer"
2626
)}

components/modal/modalComponents/ModalInput.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { bindCls } from "@/lib/utils";
1+
import { bindClass } from "@/util/bindClass";
22
import { ChangeEvent } from "react";
33

44
const ModalInput = ({
@@ -19,7 +19,7 @@ const ModalInput = ({
1919
id={name}
2020
value={value}
2121
onChange={onChange}
22-
className={bindCls(
22+
className={bindClass(
2323
"w-full rounded-lg border border-gray300 py-[18px] px-[15px] mb-6 text-black300",
2424
"placeholder:text-base placeholder:text-gray400",
2525
"focus:outline-1px focus:outline-purple100"

hooks/useDebounce.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { useEffect, useState } from "react";
2+
3+
const useDebounce = (value: any, delay: number) => {
4+
const [debouncedValue, setDebouncedValue] = useState(value);
5+
6+
useEffect(() => {
7+
const timer = setTimeout(() => {
8+
setDebouncedValue(value);
9+
}, delay);
10+
11+
return () => {
12+
clearTimeout(timer);
13+
};
14+
}, [value]);
15+
16+
return debouncedValue;
17+
};
18+
19+
export default useDebounce;

hooks/useThrottle.ts

Whitespace-only changes.

lib/utils.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,3 @@
1-
// tailwind 동적 스타일을 위한 함수
2-
export const bindCls = (...cls: string[]) => {
3-
return cls.join(" ");
4-
};
5-
61
// 데이터나 API에서 이미지 URL이 //로 오는 경우 자동으로 프로토콜 추가
72
export const ensureAbsoluteUrl = (url: string) => {
83
return url.startsWith("//") ? `https:${url}` : url;

util/bindClass.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// tailwind 동적 스타일을 위한 함수
2+
export const bindClass = (...cls: string[]) => {
3+
return cls.join(" ");
4+
};

0 commit comments

Comments
 (0)