Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 28 additions & 3 deletions src/api/task/get-task-detail.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,38 @@
import instance from "@/utils/axios";
import { notFound } from "next/navigation";

export const fetchTaskDetail = async (
groupId: number,
taskListId: number,
taskId: number,
token: string
) => {
try {
const response = await fetch(
`${process.env.NEXT_PUBLIC_API_URL}/groups/${groupId}/task-lists/${taskListId}/tasks/${taskId}`,
{
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
}
);

if (!response) return notFound();

return response.json();
} catch (error) {
console.error(error);
}
};

/**
* @author hwitae
* @description 할 일 상세 정보를 조회합니다.
* @param taskId 할 일 ID
*/
const getTaskDetail = async (
export const getTaskDetail = async (
groupId: number,
taskListId: number,
taskId: number
Expand All @@ -22,5 +49,3 @@ const getTaskDetail = async (
console.error(error);
}
};

export default getTaskDetail;
28 changes: 25 additions & 3 deletions src/api/task/get-task-list.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,31 @@
import { TaskList } from "@/types/taskList";
import instance from "@/utils/axios";

const getTaskList = async (
export const fetchTaskList = async (
groupId: number,
taskListId: number,
token: string
) => {
try {
const response = await fetch(
`${process.env.NEXT_PUBLIC_API_URL}/groups/${groupId}/task-lists/${taskListId}`,
{
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
}
);

return response.json();
} catch (error) {
console.error(error);
throw error;
}
};

export const getTaskList = async (
groupId: number,
taskListId: number,
date?: string
Expand All @@ -15,5 +39,3 @@ const getTaskList = async (
throw error;
}
};

export default getTaskList;
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Icon, Profile, TaskDetailContentSkeleton } from "@/components";
import ICONS_MAP from "@/components/icon/icons-map";
import usePatchTaskDetail from "@/hooks/api/task/use-patch-task-detail";
import { Writer } from "@/types/user";
import { ChangeEvent, useEffect, useRef, useState } from "react";
import { ChangeEvent, useEffect, useRef } from "react";
import TextareaAutosize from "react-textarea-autosize";
import TaskDetailToggleBtn from "./task-detail-complete-btn";
import { toKoreanDateWithTimeString } from "@/utils/date-util";
Expand Down Expand Up @@ -46,7 +46,6 @@ const TaskDetailContents = ({
frequency,
isPending,
}: TaskDetailContentsProps) => {
const [text, setText] = useState<string>();
const timer = useRef<NodeJS.Timeout | null>(null);
const newDescription = useRef<string>(description);
const newName = useRef<string>(name);
Expand All @@ -67,12 +66,10 @@ const TaskDetailContents = ({

const handleDescriptionChange = (e: ChangeEvent<HTMLTextAreaElement>) => {
newDescription.current = e.target.value.trim();
setText(e.target.value);
};

const handleNameChange = (e: ChangeEvent<HTMLTextAreaElement>) => {
newName.current = e.target.value.trim();
setText(e.target.value);
};

const handleToggleBtnClick = () => {
Expand Down
116 changes: 116 additions & 0 deletions src/app/[groupId]/tasklist/@task/_components/task-detail.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
"use client";

import TaskDetailComment from "../_components/task-detail-comment";
import TaskDetailContents from "../_components/task-detail-contents";
import { Icon } from "@/components";
import TaskDetailWrapper from "../_components/task-detail-wrapper";
import {
notFound,
useParams,
usePathname,
useRouter,
useSearchParams,
} from "next/navigation";
import useGetTaskDetail from "@/hooks/api/task/use-get-task-detail";
import { AnimatePresence } from "framer-motion";
import { motion } from "framer-motion";
import cn from "@/utils/clsx";
import TaskDetailInputReply from "../_components/task-detail-input-reply";

const pageVariants = {
initial: {
x: "100%",
opacity: 0,
},
visible: {
x: 0,
opacity: 1,
transition: {
type: "tween",
ease: "easeOut",
duration: 0.2,
} as const,
},
exit: {
x: "100%",
opacity: 0,
transition: {
type: "tween",
ease: "easeIn",
duration: 0.2,
} as const,
},
};

const TaskDetail = () => {
const router = useRouter();
const param = useParams();
const pathName = usePathname();
const searchParam = useSearchParams();
const taskId = Number(searchParam.get("task"));
const taskListId = Number(searchParam.get("list"));
const groupId = Number(param.groupId);

const handleClose = () => {
router.push(`${pathName}?list=${taskListId}`);
};

const { data: taskDetailData, isPending } = useGetTaskDetail(
groupId,
taskListId,
taskId
);

if (taskId) {
if (!taskDetailData) notFound();
}

return (
<AnimatePresence mode="wait">
{taskId ? (
<motion.aside
key={taskId}
variants={pageVariants}
initial="initial"
animate="visible"
exit="exit"
className={cn(
"relative left-0 z-50 flex w-full min-w-[375px] flex-col overflow-y-auto bg-white px-7 py-3",
"tablet:fixed tablet:left-auto tablet:right-0 tablet:top-0 tablet:h-screen tablet:max-w-[520px] tablet:gap-4 tablet:pt-10 tablet:drop-shadow-lg",
"pc:relative pc:left-0 pc:right-auto pc:top-auto pc:h-auto pc:max-w-[780px] pc:gap-5"
)}
>
<TaskDetailWrapper onClose={handleClose}>
<div className="flex flex-col gap-5">
<div className="flex flex-col gap-10 tablet:gap-14 pc:gap-[68px]">
<TaskDetailContents
{...taskDetailData}
createdAt={taskDetailData?.recurring?.createdAt}
groupId={groupId}
taskListId={taskListId}
taskId={taskId}
isPending={isPending}
/>
<div className="flex flex-col gap-4">
<div className="flex items-center gap-1">
<Icon
icon="comment"
className="h-[18px] w-[18px] tablet:h-5 tablet:w-5"
/>
<span className="text-lg font-bold text-blue-200">
{taskDetailData?.commentCount || 0}
</span>
</div>
<TaskDetailInputReply taskId={taskId} />
</div>
</div>
<TaskDetailComment taskId={taskId} />
</div>
</TaskDetailWrapper>
</motion.aside>
) : null}
</AnimatePresence>
);
};

export default TaskDetail;
111 changes: 2 additions & 109 deletions src/app/[groupId]/tasklist/@task/page.tsx
Original file line number Diff line number Diff line change
@@ -1,114 +1,7 @@
"use client";

import TaskDetailComment from "./_components/task-detail-comment";
import TaskDetailContents from "./_components/task-detail-contents";
import { Icon, InputReply } from "@/components";
import TaskDetailWrapper from "./_components/task-detail-wrapper";
import {
useParams,
usePathname,
useRouter,
useSearchParams,
} from "next/navigation";
import useGetTaskDetail from "@/hooks/api/task/use-get-task-detail";
import { AnimatePresence } from "framer-motion";
import { useCreateComment } from "@/hooks/api/comments/use-create-comment";
import { motion } from "framer-motion";
import cn from "@/utils/clsx";
import TaskDetailInputReply from "./_components/task-detail-input-reply";

const pageVariants = {
initial: {
x: "100%",
opacity: 0,
},
visible: {
x: 0,
opacity: 1,
transition: {
type: "tween",
ease: "easeOut",
duration: 0.2,
} as const,
},
exit: {
x: "100%",
opacity: 0,
transition: {
type: "tween",
ease: "easeIn",
duration: 0.2,
} as const,
},
};
import TaskDetail from "./_components/task-detail";

const Page = () => {
const router = useRouter();
const param = useParams();
const pathName = usePathname();
const searchParam = useSearchParams();
const taskId = Number(searchParam.get("task"));
const taskListId = Number(searchParam.get("list"));
const groupId = Number(param.groupId);

const handleClose = () => {
router.push(`${pathName}?list=${taskListId}`);
};

const { data: taskDetailData, isPending } = useGetTaskDetail(
groupId,
taskListId,
taskId
);

const { mutate: postTaskDetailComment } = useCreateComment(taskId);

return (
<AnimatePresence mode="wait">
{taskId ? (
<motion.aside
key={taskId}
variants={pageVariants}
initial="initial"
animate="visible"
exit="exit"
className={cn(
"relative left-0 z-50 flex w-full min-w-[375px] flex-col overflow-y-auto bg-white px-7 py-3",
"tablet:fixed tablet:left-auto tablet:right-0 tablet:top-0 tablet:h-screen tablet:max-w-[520px] tablet:gap-4 tablet:pt-10 tablet:drop-shadow-lg",
"pc:relative pc:left-0 pc:right-auto pc:top-auto pc:h-auto pc:max-w-[780px] pc:gap-5"
)}
>
<TaskDetailWrapper onClose={handleClose}>
<div className="flex flex-col gap-5">
<div className="flex flex-col gap-10 tablet:gap-14 pc:gap-[68px]">
<TaskDetailContents
{...taskDetailData}
createdAt={taskDetailData?.recurring?.createdAt}
groupId={groupId}
taskListId={taskListId}
taskId={taskId}
isPending={isPending}
/>
<div className="flex flex-col gap-4">
<div className="flex items-center gap-1">
<Icon
icon="comment"
className="h-[18px] w-[18px] tablet:h-5 tablet:w-5"
/>
<span className="text-lg font-bold text-blue-200">
{taskDetailData?.commentCount || 0}
</span>
</div>
<TaskDetailInputReply taskId={taskId} />
</div>
</div>
<TaskDetailComment taskId={taskId} />
</div>
</TaskDetailWrapper>
</motion.aside>
) : null}
</AnimatePresence>
);
return <TaskDetail />;
};

export default Page;
1 change: 1 addition & 0 deletions src/app/[groupId]/tasklist/_components/task-list-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const TaskListItem = ({
alt="empty_task"
quality={100}
draggable={false}
priority
/>
<p className="text-center text-md text-gray-700">
할 일이 없네요
Expand Down
Loading