From 2040e5f266b7ac257e436f11ae52c9833f83aa29 Mon Sep 17 00:00:00 2001 From: Seongsuk Hong Date: Sun, 5 Jan 2025 13:23:25 +0900 Subject: [PATCH 1/6] =?UTF-8?q?=F0=9F=90=9BFix:=20SignUpPage=20redirectTo?= =?UTF-8?q?=20=ED=83=80=EC=9E=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/(unauthorized)/signup/page.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/(unauthorized)/signup/page.tsx b/src/app/(unauthorized)/signup/page.tsx index aa40198..642a94c 100644 --- a/src/app/(unauthorized)/signup/page.tsx +++ b/src/app/(unauthorized)/signup/page.tsx @@ -16,9 +16,9 @@ interface ISignUpFormInputs { passwordConfirm: string; } export default function SignUpPage({ - searchParams: redirectTo, + searchParams, }: { - searchParams: string; + searchParams: { redirectTo?: string }; }) { const { register, @@ -44,8 +44,8 @@ export default function SignUpPage({ redirect: false, }); if (res?.ok) { - if (redirectTo) { - router.push(redirectTo); + if (searchParams.redirectTo) { + router.push(searchParams.redirectTo); } else { router.push('/'); } From 874571b09b3c8c997a777fc085c99942f0729cfe Mon Sep 17 00:00:00 2001 From: Seongsuk Hong Date: Sun, 5 Jan 2025 13:24:14 +0900 Subject: [PATCH 2/6] =?UTF-8?q?=F0=9F=92=A1Comment:=20=EC=B9=B4=EC=B9=B4?= =?UTF-8?q?=EC=98=A4=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EC=9E=84=EC=8B=9C=20?= =?UTF-8?q?=EC=A3=BC=EC=84=9D=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/(unauthorized)/signin/page.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/app/(unauthorized)/signin/page.tsx b/src/app/(unauthorized)/signin/page.tsx index 77b100f..f9c16f5 100644 --- a/src/app/(unauthorized)/signin/page.tsx +++ b/src/app/(unauthorized)/signin/page.tsx @@ -1,6 +1,6 @@ 'use client'; -import Image from 'next/image'; +// import Image from 'next/image'; import Link from 'next/link'; import { SubmitHandler, useForm } from 'react-hook-form'; import { AUTH_VALIDATION_REGEX } from '@constant/auth'; @@ -98,7 +98,8 @@ export default function SignInPage({ > 로그인하기 - + */}
From ffd38879e0cb99f0d574ebda142dd07cb1bdbc5d Mon Sep 17 00:00:00 2001 From: Seongsuk Hong Date: Sun, 5 Jan 2025 13:27:48 +0900 Subject: [PATCH 3/6] =?UTF-8?q?=F0=9F=90=9BFix:=20ProgressBar=20=EC=8A=A4?= =?UTF-8?q?=ED=83=80=EC=9D=BC=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=20?= =?UTF-8?q?=EC=95=88=20=EB=90=98=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 할 일 취소시 프로그래스바 스타일 업데이트 안 되는 문제는 useEffect에서 value가 0일 때 setProgress가 호출되지 않는 조건 수정 해결 - 필터 선택 시 스타일이 즉시 업데이트되지 않는 문제 해결 - API 호출 시 React Query의 invalidateQueries를 사용하여 ['tasks', 'list'] 쿼리 키를 가진 데이터를 전부 재호출하도록 처리 - 선택된 필터 카테고리와 관련된 데이터를 최신 상태로 유지 --- components/ui/progress.tsx | 6 ++---- src/hooks/task/usePutCompleteTask.ts | 8 +------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/components/ui/progress.tsx b/components/ui/progress.tsx index 3bbd183..98cf9ba 100644 --- a/components/ui/progress.tsx +++ b/components/ui/progress.tsx @@ -19,10 +19,8 @@ const Progress = React.forwardRef< const [progress, setProgress] = React.useState(0); React.useEffect(() => { - if (value) { - const timer = setTimeout(() => setProgress(value), 500); - return () => clearTimeout(timer); - } + const timer = setTimeout(() => setProgress(value || 0), 200); + return () => clearTimeout(timer); }, [value]); return ( diff --git a/src/hooks/task/usePutCompleteTask.ts b/src/hooks/task/usePutCompleteTask.ts index 4cade1f..50c015a 100644 --- a/src/hooks/task/usePutCompleteTask.ts +++ b/src/hooks/task/usePutCompleteTask.ts @@ -1,4 +1,3 @@ -import { tasksQueryKeys } from '@constant/queryKeyFactory'; import { putCompleteTask } from '@lib/api/service/task.api'; import { TPutCompleteTaskRequest } from '@model/task.model'; import { useMutation, useQueryClient } from '@tanstack/react-query'; @@ -12,13 +11,8 @@ export const usePutCompleteTask = () => { }, onSuccess: (response) => { if (response.success) { - const props = { - tripId: response.result.tripId, - taskSeq: 0, - all: true, - }; queryClient.invalidateQueries({ - queryKey: tasksQueryKeys.list(props).queryKey, + queryKey: ['tasks', 'list'], }); } }, From bfae21b6bf62460955ae0bebd80273e0eda797b6 Mon Sep 17 00:00:00 2001 From: Seongsuk Hong Date: Sun, 5 Jan 2025 13:50:43 +0900 Subject: [PATCH 4/6] =?UTF-8?q?=F0=9F=92=84Design:=20=EC=97=AC=ED=96=89=20?= =?UTF-8?q?=EC=95=84=EC=9D=B4=EC=BD=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ui/box/TripBox.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/box/TripBox.tsx b/src/ui/box/TripBox.tsx index ac96b36..b10d49f 100644 --- a/src/ui/box/TripBox.tsx +++ b/src/ui/box/TripBox.tsx @@ -51,8 +51,8 @@ export default function TripBox({ id, name }: ITripCardProps) {
From 424cfcd90f281091284abf8a510a3ebd7ae7aa08 Mon Sep 17 00:00:00 2001 From: Seongsuk Hong Date: Sun, 5 Jan 2025 14:43:32 +0900 Subject: [PATCH 5/6] =?UTF-8?q?=F0=9F=90=9BFix:=20=EC=97=AC=ED=96=89=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=EC=97=90=EC=84=9C=20=EC=B5=9C=EC=B4=88=20?= =?UTF-8?q?=ED=95=84=ED=84=B0=20=EB=B2=84=ED=8A=BC=20=ED=81=B4=EB=A6=AD?= =?UTF-8?q?=EC=8B=9C=20=EC=8A=A4=ED=83=80=EC=9D=BC=20=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8=20=EC=95=88=EB=90=98=EB=8A=94=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - FilterButton 컴포넌트에서 로컬 상태 제거 및 props 업데이트 - TripTask 컴포넌트에서 activeFilter 상태 관리 추가 - FilterType을 사용하여 타입 생성 - 모든 할일 페이지와 TripBox도 맞춰 로직 수정 --- src/app/(authorized)/todo-all/page.tsx | 26 ++++++++++------ src/ui/box/TripBox.tsx | 27 +++++++++------- src/ui/common/FilterButton.tsx | 23 ++++++-------- src/ui/skeleton/Skeletons.tsx | 22 +++++-------- src/ui/trip/TripTask.tsx | 43 ++++++++++++++------------ 5 files changed, 75 insertions(+), 66 deletions(-) diff --git a/src/app/(authorized)/todo-all/page.tsx b/src/app/(authorized)/todo-all/page.tsx index aa088e4..7d40260 100644 --- a/src/app/(authorized)/todo-all/page.tsx +++ b/src/app/(authorized)/todo-all/page.tsx @@ -1,12 +1,12 @@ 'use client'; + import { EMPTY_TASK_MESSAGE, FILTER_MAPPING } from '@constant/task'; import { useGetTasks } from '@hooks/task/useGetTasks'; import { usePostTask } from '@hooks/task/usePostTask'; -import { TTaskScope } from '@model/task.model'; import { useModalStore } from '@store/modal.store'; import TaskList from '@ui/card/taskCard/TaskList'; import EmptyMessage from '@ui/common/EmptyMessage'; -import FilterButton from '@ui/common/FilterButton'; +import FilterButton, { TFilterType } from '@ui/common/FilterButton'; import NavTitle from '@ui/common/NavTitle'; import TodoModal from '@ui/Modal/TodoModal'; import { AllTodoPageSkeleton } from '@ui/skeleton/Skeletons'; @@ -14,12 +14,12 @@ import AddTaskButton from '@ui/trip/tripTask/AddTaskButton'; import { useState } from 'react'; export default function TodoAllPage() { - const [taskScope, setTaskScope] = useState(null); - const params = { + const [activeFilter, setActiveFilter] = useState('All'); + const [params, setParams] = useState({ taskSeq: 0, all: true, - ...(taskScope ? { taskScope } : {}), - }; + }); + const { showModal } = useModalStore(); const postTask = usePostTask(); const handleAddTaskClick = () => { @@ -29,9 +29,14 @@ export default function TodoAllPage() { }); }; const { data: tasks, isLoading: isTasksLoading } = useGetTasks(params); - const handleTaskFilterClick = (filter: string) => { + + const handleTaskFilterClick = (filter: TFilterType) => { + setActiveFilter(filter); const scope = FILTER_MAPPING[filter]; - setTaskScope(scope); + setParams((prev) => ({ + ...prev, + taskScope: scope || null, + })); }; if (isTasksLoading) { @@ -50,7 +55,10 @@ export default function TodoAllPage() {
- + handleTaskFilterClick(filter)} + /> {tasks?.result && tasks?.result.length > 0 ? ( ) : ( diff --git a/src/ui/box/TripBox.tsx b/src/ui/box/TripBox.tsx index b10d49f..1032f59 100644 --- a/src/ui/box/TripBox.tsx +++ b/src/ui/box/TripBox.tsx @@ -1,9 +1,8 @@ import Subtitle from '@ui/common/Subtitle'; -import FilterButton from '@ui/common/FilterButton'; +import FilterButton, { TFilterType } from '@ui/common/FilterButton'; import TaskCarousel from '@ui/carousel/TaskCarousel'; import ShowAllTasksButton from '@ui/trip/tripTask/ShowAllTasksButton'; import AddTaskButton from '@ui/trip/tripTask/AddTaskButton'; -import { TTaskScope } from '@model/task.model'; import { useRouter } from 'next/navigation'; import { useModalStore } from '@store/modal.store'; import { FILTER_MAPPING } from '@constant/task'; @@ -12,28 +11,31 @@ import { useGetTasks } from '@hooks/task/useGetTasks'; import TodoModal from '@ui/Modal/TodoModal'; import { usePostTask } from '@hooks/task/usePostTask'; -/* eslint-disable @typescript-eslint/no-unused-vars */ - interface ITripCardProps { id: number; name: string; } export default function TripBox({ id, name }: ITripCardProps) { - const [taskScope, setTaskScope] = useState(null); - const params = { + const [activeFilter, setActiveFilter] = useState('All'); + const [params, setParams] = useState({ tripId: id, taskSeq: 0, all: true, - ...(taskScope ? { taskScope } : {}), - }; + }); + const postTask = usePostTask(); const { data: tasks } = useGetTasks(params); const navigate = useRouter(); const { showModal } = useModalStore(); - const handleTaskFilterClick = (filter: string) => { + + const handleTaskFilterClick = (filter: TFilterType) => { + setActiveFilter(filter); const scope = FILTER_MAPPING[filter]; - setTaskScope(scope); + setParams((prev) => ({ + ...prev, + taskScope: scope || null, + })); }; const handleAddTaskClick = () => { @@ -58,7 +60,10 @@ export default function TripBox({ id, name }: ITripCardProps) {
- + handleTaskFilterClick(filter)} + />
diff --git a/src/ui/common/FilterButton.tsx b/src/ui/common/FilterButton.tsx index 7ee7a8b..f456636 100644 --- a/src/ui/common/FilterButton.tsx +++ b/src/ui/common/FilterButton.tsx @@ -1,30 +1,27 @@ 'use client'; -import { useState } from 'react'; import { twMerge } from 'tailwind-merge'; -const FILTERS = ['All', '공통', '개인']; +export const FILTERS = ['All', '공통', '개인'] as const; +export type TFilterType = (typeof FILTERS)[number]; interface IFilterButtonProps { - onClick: (filter: string) => void; // 클릭 이벤트 핸들러 + activeFilter: TFilterType; // 필터 상태 + onClick: (filter: TFilterType) => void; // 클릭 이벤트 핸들러 } -export default function FilterButton({ onClick }: IFilterButtonProps) { - const [activeFilter, setActiveFilter] = useState('All'); - - const handleFilterClick = (filter: string) => { - setActiveFilter(filter); - onClick(filter); - }; - +export default function FilterButton({ + activeFilter, + onClick, +}: IFilterButtonProps) { return (
{FILTERS.map((filter) => ( - + {items?.map((item, index) => (