From ab60d014cf8579b2c6450223e313e9d6dbc35881 Mon Sep 17 00:00:00 2001
From: Jeong Daseul <98886223+goodaseul@users.noreply.github.com>
Date: Wed, 31 Dec 2025 16:28:38 +0900
Subject: [PATCH 1/4] =?UTF-8?q?=F0=9F=9A=A8=20Fix=20:=20=EB=AA=A9=ED=91=9C?=
=?UTF-8?q?=EC=83=81=EC=84=B8=20-=20=EC=88=98=EC=A0=95=EB=B0=8F=20?=
=?UTF-8?q?=EC=B7=A8=EC=86=8C=EA=B8=B0=EB=8A=A5=20=ED=85=8C=EC=8A=A4?=
=?UTF-8?q?=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=A0=81=EC=9A=A9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../goals/[goalId]/_components/GoalHeader.tsx | 24 +++++++++++++++----
.../common/input/base-input/BaseInput.tsx | 3 +++
tests/unit/goals/goals.test.tsx | 22 ++++++++++++++++-
3 files changed, 43 insertions(+), 6 deletions(-)
diff --git a/src/app/(protected)/goals/[goalId]/_components/GoalHeader.tsx b/src/app/(protected)/goals/[goalId]/_components/GoalHeader.tsx
index a7766c1..08427b2 100644
--- a/src/app/(protected)/goals/[goalId]/_components/GoalHeader.tsx
+++ b/src/app/(protected)/goals/[goalId]/_components/GoalHeader.tsx
@@ -11,6 +11,7 @@ import { useDeleteGoalMutation } from "@/hooks/queries/goals/useDeleteGoalMutati
import ConfirmModal from "@/components/common/popup-modal/ConfirmModal";
import { useRouter } from "next/navigation";
import { toast } from "@/lib/toast";
+import BaseInput from "@/components/common/input/base-input/BaseInput";
type GoalHeaderProps = {
goalId: string;
@@ -41,7 +42,7 @@ export default function GoalHeader({ goalId }: GoalHeaderProps) {
text: "수정하기",
onClick: () => {
closeDropdown();
- setEditTitle(goal?.title ?? "");
+ setEditTitle("");
setIsEditing(true);
},
},
@@ -66,6 +67,11 @@ export default function GoalHeader({ goalId }: GoalHeaderProps) {
);
};
+ const handleCancelEdit = () => {
+ setEditTitle("");
+ setIsEditing(false);
+ };
+
const handleConfim = () => {
deleteGoal(numericGoalId, {
onSuccess: () => {
@@ -86,11 +92,13 @@ export default function GoalHeader({ goalId }: GoalHeaderProps) {
{goal?.title}
) : (
- setEditTitle(e.target.value)}
+ placeholder="수정할 목표를 적어주세요."
onKeyDown={(e) => {
if (e.key === "Enter") {
e.preventDefault();
@@ -98,10 +106,16 @@ export default function GoalHeader({ goalId }: GoalHeaderProps) {
}
}}
/>
+
- 수정 완료
+ 수정
+
+
+ 취소
)}
diff --git a/src/components/common/input/base-input/BaseInput.tsx b/src/components/common/input/base-input/BaseInput.tsx
index 19885ad..6c4aab4 100644
--- a/src/components/common/input/base-input/BaseInput.tsx
+++ b/src/components/common/input/base-input/BaseInput.tsx
@@ -9,6 +9,7 @@ export interface BaseInputProps {
id?: string;
value: string;
onChange: (e: React.ChangeEvent) => void;
+ onKeyDown?: (e: React.KeyboardEvent) => void;
placeholder?: string;
type?: InputType;
className?: string;
@@ -20,6 +21,7 @@ export default function BaseInput({
id,
value,
onChange,
+ onKeyDown,
placeholder = "",
type = "text",
className,
@@ -46,6 +48,7 @@ export default function BaseInput({
value={value}
placeholder={placeholder}
onChange={onChange}
+ onKeyDown={onKeyDown}
className={inputClassName}
/>
{rightIcon}
diff --git a/tests/unit/goals/goals.test.tsx b/tests/unit/goals/goals.test.tsx
index 0518c61..784c3db 100644
--- a/tests/unit/goals/goals.test.tsx
+++ b/tests/unit/goals/goals.test.tsx
@@ -34,6 +34,26 @@ describe("목표 영역", () => {
expect(screen.getByText("수정하기")).toBeInTheDocument();
expect(screen.getByText("삭제하기")).toBeInTheDocument();
});
+ it("목표 수정 중 취소를 누르면 수정 모드가 종료된다", async () => {
+ const user = userEvent.setup();
+
+ renderWithQueryClient();
+
+ await user.click(screen.getByLabelText("goal-options"));
+ await user.click(screen.getByText("수정하기"));
+
+ const input = screen.getByRole("textbox");
+ expect(input).toBeInTheDocument();
+
+ await user.type(input, "할일");
+
+ await user.click(screen.getByText("취소"));
+
+ expect(screen.queryByRole("textbox")).not.toBeInTheDocument();
+
+ expect(updateGoal).not.toHaveBeenCalled();
+ });
+
it("목표를 수정하면 입력한 값으로 변경된다", async () => {
const user = userEvent.setup();
(updateGoal as jest.Mock).mockResolvedValueOnce({
@@ -53,7 +73,7 @@ describe("목표 영역", () => {
await user.clear(input);
await user.type(input, "새 목표");
- await user.click(screen.getByText("수정 완료"));
+ await user.click(screen.getByText("수정"));
expect(await screen.findByText("새 목표")).toBeInTheDocument();
From e54a276808676eae9fb7898f46720e5b56a58930 Mon Sep 17 00:00:00 2001
From: Jeong Daseul <98886223+goodaseul@users.noreply.github.com>
Date: Wed, 31 Dec 2025 17:19:04 +0900
Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=92=84=20Style=20:=20=EB=8C=80?=
=?UTF-8?q?=EC=8B=9C=EB=B3=B4=EB=93=9C=20=EC=B5=9C=EA=B7=BC=EB=93=B1?=
=?UTF-8?q?=EB=A1=9D/=EC=A7=84=ED=96=89=EB=8F=84=20=EC=97=90=EB=9F=AC?=
=?UTF-8?q?=EB=B0=94=EC=9A=B4=EB=8D=94=EB=A6=AC=20=ED=83=9C=EA=B7=B8?=
=?UTF-8?q?=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../todos/progress/ProgressTodos.tsx | 17 ++++++++++++++++-
.../_components/todos/recent/RecentTodos.tsx | 19 +++++++++++++++++--
2 files changed, 33 insertions(+), 3 deletions(-)
diff --git a/src/app/(protected)/dashboard/_components/todos/progress/ProgressTodos.tsx b/src/app/(protected)/dashboard/_components/todos/progress/ProgressTodos.tsx
index 7a251f9..a8f4517 100644
--- a/src/app/(protected)/dashboard/_components/todos/progress/ProgressTodos.tsx
+++ b/src/app/(protected)/dashboard/_components/todos/progress/ProgressTodos.tsx
@@ -3,6 +3,8 @@ import ProgressCardSkeleton from "@/components/skeleton/ProgressCardSkeleton";
import ProgressContent from "./ProgressContent";
import { useAuthStore } from "@/store/useAuthStore";
import { AsyncBoundary } from "@/app/(protected)/_components/AsyncBoundary";
+import { FallbackProps } from "react-error-boundary";
+import Button from "@/components/common/button/Button";
export default function ProgressTodos() {
const user = useAuthStore((state) => state.user);
@@ -22,7 +24,20 @@ export default function ProgressTodos() {
-
}>
+
}
+ errorFallback={({ error, resetErrorBoundary }: FallbackProps) => (
+
+
+ {error.message}
+
+
+
+ )}>
diff --git a/src/app/(protected)/dashboard/_components/todos/recent/RecentTodos.tsx b/src/app/(protected)/dashboard/_components/todos/recent/RecentTodos.tsx
index 5d63441..6cf2948 100644
--- a/src/app/(protected)/dashboard/_components/todos/recent/RecentTodos.tsx
+++ b/src/app/(protected)/dashboard/_components/todos/recent/RecentTodos.tsx
@@ -4,6 +4,8 @@ import { ChevronRightIcon } from "@heroicons/react/24/outline";
import { ListSkeleton } from "@/components/skeleton/ListSkeleton";
import RecentTodosContent from "./RecentTodosContent";
import { AsyncBoundary } from "@/app/(protected)/_components/AsyncBoundary";
+import { FallbackProps } from "react-error-boundary";
+import Button from "@/components/common/button/Button";
export default function RecentTodos() {
return (
@@ -30,9 +32,22 @@ export default function RecentTodos() {
loadingFallback={
- }>
+ }
+ errorFallback={({ error, resetErrorBoundary }: FallbackProps) => (
+
+
+ {error.message}
+
+
+
+ )}>
From 45a55b41e0077f92fa4f4922f072777000250d51 Mon Sep 17 00:00:00 2001
From: Jeong Daseul <98886223+goodaseul@users.noreply.github.com>
Date: Wed, 31 Dec 2025 17:31:03 +0900
Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=92=84=20Style=20:=20=EC=97=90?=
=?UTF-8?q?=EB=9F=AC=20=EB=B0=94=EC=9A=B4=EB=8D=94=EB=A6=AC=20=EC=83=89?=
=?UTF-8?q?=EC=83=81=20=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../_components/goal/GoalSkeleton.tsx | 9 ++++-----
.../_components/GoalContainerSkeleton.tsx | 19 ++++++++-----------
2 files changed, 12 insertions(+), 16 deletions(-)
diff --git a/src/app/(protected)/dashboard/_components/goal/GoalSkeleton.tsx b/src/app/(protected)/dashboard/_components/goal/GoalSkeleton.tsx
index bdf4bfc..b65c012 100644
--- a/src/app/(protected)/dashboard/_components/goal/GoalSkeleton.tsx
+++ b/src/app/(protected)/dashboard/_components/goal/GoalSkeleton.tsx
@@ -9,13 +9,13 @@ export default function GoalSkeleton() {
@@ -33,7 +33,6 @@ export default function GoalSkeleton() {
title="DONE"
variant="done">
diff --git a/src/app/(protected)/goals/[goalId]/_components/GoalContainerSkeleton.tsx b/src/app/(protected)/goals/[goalId]/_components/GoalContainerSkeleton.tsx
index 62a24a0..cabcfdc 100644
--- a/src/app/(protected)/goals/[goalId]/_components/GoalContainerSkeleton.tsx
+++ b/src/app/(protected)/goals/[goalId]/_components/GoalContainerSkeleton.tsx
@@ -3,31 +3,27 @@ import { ListSkeleton } from "@/components/skeleton/ListSkeleton";
export default function GoalContainerSkeleton() {
return (
-
-
@@ -36,6 +32,7 @@ export default function GoalContainerSkeleton() {
From baa89b9ba97e8a809b6ea3d47ef07f248ca378b1 Mon Sep 17 00:00:00 2001
From: Jeong Daseul <98886223+goodaseul@users.noreply.github.com>
Date: Wed, 31 Dec 2025 18:04:27 +0900
Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=9A=A8=20Fix=20:=20=EB=AA=A9=ED=91=9C?=
=?UTF-8?q?=EC=83=81=EC=84=B8=20=EC=8A=A4=ED=81=AC=EB=A1=A4=202=EA=B0=9C?=
=?UTF-8?q?=20=EC=9D=B4=EC=8A=88=20=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../goals/[goalId]/_components/Goal.tsx | 1 +
.../_components/GoalContainerData.tsx | 19 +++++++++++++++++++
.../[goalId]/_components/GoalSection.tsx | 2 +-
3 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/src/app/(protected)/goals/[goalId]/_components/Goal.tsx b/src/app/(protected)/goals/[goalId]/_components/Goal.tsx
index 562dc7e..df60db2 100644
--- a/src/app/(protected)/goals/[goalId]/_components/Goal.tsx
+++ b/src/app/(protected)/goals/[goalId]/_components/Goal.tsx
@@ -9,6 +9,7 @@ export default function Goal({ goalTodos }: { goalTodos: ListTodoType[] }) {
const goalTodoChecked = goalTodos.filter((goalTodo) => !goalTodo.checked);
const goalTodoCheckedDone = goalTodos.filter((goalTodo) => goalTodo.checked);
+
return (
0 ? goalTodos[0].id : null;
+ useEffect(() => {
+ const handleResize = () => {
+ if (window.innerWidth >= 640) {
+ document.body.style.overflow = "hidden";
+ } else {
+ document.body.style.overflow = "";
+ }
+ };
+
+ handleResize();
+
+ window.addEventListener("resize", handleResize);
+
+ return () => {
+ window.removeEventListener("resize", handleResize);
+ document.body.style.overflow = "";
+ };
+ }, []);
return (
<>
diff --git a/src/app/(protected)/goals/[goalId]/_components/GoalSection.tsx b/src/app/(protected)/goals/[goalId]/_components/GoalSection.tsx
index bc8e05e..219cc7a 100644
--- a/src/app/(protected)/goals/[goalId]/_components/GoalSection.tsx
+++ b/src/app/(protected)/goals/[goalId]/_components/GoalSection.tsx
@@ -42,7 +42,7 @@ export default function GoalSection({
className="grid sm:gap-0.5 lg:gap-1"
items={items}
onToggleChecked={onToggleChecked}
- containerClassName="sm:h-110"
+ containerClassName="sm:h-110 overflow-hidden overflow-y-auto"
/>
)}