Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEAT] Task 상태 수정 api (드래그앤드롭 부분 우선 구현) #192

Merged
merged 8 commits into from
Jul 18, 2024
9 changes: 9 additions & 0 deletions src/apis/tasks/getTask/GetTasksResponse.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { TaskType } from '@/types/tasks/taskType';

export interface GetTasksResponse {
code: string;
data: {
tasks: TaskType[];
};
message: string | null;
}
33 changes: 7 additions & 26 deletions src/apis/tasks/getTask/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,18 @@ import { useQuery } from '@tanstack/react-query';
import getTasks from './axios';
import { GetTasksType } from './GetTasksType';

const placeholderData = {
code: 'success',
data: {
tasks: [
{
id: 1,
name: 'task name',
deadLine: {
date: '2024-06-30',
time: '12:30',
},
},
{
id: 2,
name: 'task name',
deadLine: {
date: '2024-06-30',
time: '12:30',
},
},
],
},
message: null,
};

/** Task 리스트 조회 */
const useGetTasks = ({ isTotal, sortOrder, targetDate }: GetTasksType) =>
useQuery({
queryKey: ['today', isTotal, sortOrder, targetDate],
queryFn: () => getTasks({ isTotal, sortOrder, targetDate }),
placeholderData,
placeholderData: {
code: 'success',
data: {
tasks: [],
},
message: null,
},
});

export default useGetTasks;
5 changes: 5 additions & 0 deletions src/apis/tasks/updateTaskStatus/UpdateTaskStatusType.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface UpdateTaskStatusType {
taskId: number;
targetDate?: string | null;
status?: string | null;
Comment on lines +2 to +4
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

옵셔널로 해주고 또 null까지 처리해주신 이유가 뭔가용?-? (진짜 몰라서 그럼,,)

}
12 changes: 12 additions & 0 deletions src/apis/tasks/updateTaskStatus/axios.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { UpdateTaskStatusType } from './UpdateTaskStatusType';

import { privateInstance } from '@/apis/instance';

const updateTaskStatus = async ({ taskId, targetDate, status }: UpdateTaskStatusType) => {
await privateInstance.patch(`/api/tasks/${taskId}/status`, {
targetDate,
status,
});
};

export default updateTaskStatus;
17 changes: 17 additions & 0 deletions src/apis/tasks/updateTaskStatus/query.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { useMutation, useQueryClient } from '@tanstack/react-query';

import updateTaskStatus from './axios';
import { UpdateTaskStatusType } from './UpdateTaskStatusType';

const useUpdateTaskStatus = () => {
const queryClient = useQueryClient();

const mutation = useMutation({
mutationFn: (updateData: UpdateTaskStatusType) => updateTaskStatus(updateData),
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['today'] }),
});

return { mutate: mutation.mutate, queryClient };
};

export default useUpdateTaskStatus;
14 changes: 12 additions & 2 deletions src/components/common/StagingArea/StagingArea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,31 @@ import { Droppable } from 'react-beautiful-dnd';

import StagingAreaTaskContainer from './StagingAreaTaskContainer';

import StagingAreaSetting from '@/components/common/StagingArea/StagingAreaSetting';
import TextInputStaging from '@/components/common/textbox/TextInputStaging';
import { TaskType } from '@/types/tasks/taskType';
import { StagingAreaSettingProps } from '@/types/today/stagingAreaSettingProps';

interface StagingAreaProps {
interface StagingAreaProps extends StagingAreaSettingProps {
handleSelectedTarget: (task: TaskType | null) => void;
selectedTarget: TaskType | null;
tasks: TaskType[];
}

function StagingArea(props: StagingAreaProps) {
const { handleSelectedTarget, selectedTarget, tasks } = props;
const { handleSelectedTarget, selectedTarget, tasks, activeButton, sortOrder, handleTextBtnClick, handleSortOrder } =
props;
return (
<StagingAreaLayout>
<StagingAreaContainer>
<StagingAreaUpContainer>
<StagingAreaTitle>쏟아내기</StagingAreaTitle>
<StagingAreaSetting
handleTextBtnClick={handleTextBtnClick}
activeButton={activeButton}
sortOrder={sortOrder}
handleSortOrder={handleSortOrder}
/>
<Droppable droppableId="staging">
{(provided) => (
<div ref={provided.innerRef} {...provided.droppableProps}>
Expand Down
8 changes: 1 addition & 7 deletions src/components/common/StagingArea/StagingAreaSetting.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,8 @@ import TextBtn from '../button/textBtn/TextBtn';
import ModalArrange from '../modal/ModalArrange/ModalArrange';
import ModalBackdrop from '../modal/ModalBackdrop';

import { SortOrderType } from '@/types/sortOrderType';
import { StagingAreaSettingProps } from '@/types/today/stagingAreaSettingProps';

interface StagingAreaSettingProps {
handleTextBtnClick: (button: '전체' | '지연') => void;
activeButton: '전체' | '지연';
sortOrder: SortOrderType;
handleSortOrder: (order: SortOrderType) => void;
}
function StagingAreaSetting({ handleTextBtnClick, activeButton, sortOrder, handleSortOrder }: StagingAreaSettingProps) {
const [isModalOpen, setIsModalOpen] = useState(false);

Expand Down
48 changes: 9 additions & 39 deletions src/components/common/StagingArea/StagingAreaTaskContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
import styled from '@emotion/styled';
import { useState } from 'react';
import { Draggable } from 'react-beautiful-dnd';

import BtnTaskContainer from '../BtnTaskContainer';
import EmptyContainer from '../EmptyContainer';
import ScrollGradient from '../ScrollGradient';

import useGetTasks from '@/apis/tasks/getTask/query';
import BtnTask from '@/components/common/BtnTask/BtnTask';
import StagingAreaSetting from '@/components/common/StagingArea/StagingAreaSetting';
import { SortOrderType } from '@/types/sortOrderType';
import { TaskType } from '@/types/tasks/taskType';

interface StagingAreaTaskContainerProps {
Expand All @@ -18,38 +13,15 @@ interface StagingAreaTaskContainerProps {
tasks: TaskType[];
}

function StagingAreaTaskContainer({ handleSelectedTarget, selectedTarget }: StagingAreaTaskContainerProps) {
const [activeButton, setActiveButton] = useState<'전체' | '지연'>('전체');
const [sortOrder, setSortOrder] = useState<SortOrderType>('recent');
const isTotal = activeButton === '전체';

// Task 목록 Get
const { data } = useGetTasks({ isTotal, sortOrder });

/** isTotal 핸들링 함수 */
const handleTextBtnClick = (button: '전체' | '지연') => {
setActiveButton(button);
};

const handleSortOrder = (order: SortOrderType) => {
setSortOrder(order);
};
console.log(data);

function StagingAreaTaskContainer({ handleSelectedTarget, selectedTarget, tasks }: StagingAreaTaskContainerProps) {
return (
<StagingAreaTaskContainerLayout>
<StagingAreaSetting
handleTextBtnClick={handleTextBtnClick}
activeButton={activeButton}
sortOrder={sortOrder}
handleSortOrder={handleSortOrder}
/>
<BtnTaskContainer type="staging">
{data.data.tasks.length === 0 ? (
{tasks.length === 0 ? (
<EmptyContainer />
) : (
<>
{data.data.tasks.map((task: TaskType, index: number) => (
{tasks.map((task: TaskType, index: number) => (
<Draggable key={task.id} draggableId={task.id.toString()} index={index}>
{(provided, snapshot) => (
<div
Expand All @@ -59,15 +31,15 @@ function StagingAreaTaskContainer({ handleSelectedTarget, selectedTarget }: Stag
style={{ userSelect: 'none', ...provided.draggableProps.style }}
>
<BtnTask
key={task.id + task.name}
iconType="stagingOrDelayed"
iconType="active"
key={task.id}
hasDescription={task.hasDescription}
id={task.id}
name={task.name}
status={task.status}
deadLine={task.deadLine}
selectedTarget={selectedTarget}
status={task.status}
id={task.id}
handleSelectedTarget={handleSelectedTarget}
selectedTarget={selectedTarget}
isDragging={snapshot.isDragging}
/>
</div>
Expand All @@ -76,8 +48,6 @@ function StagingAreaTaskContainer({ handleSelectedTarget, selectedTarget }: Stag
))}
</>
)}

<ScrollGradient />
</BtnTaskContainer>
</StagingAreaTaskContainerLayout>
);
Expand All @@ -88,7 +58,7 @@ export default StagingAreaTaskContainer;
const StagingAreaTaskContainerLayout = styled.div`
display: flex;
flex-direction: column;
gap: 1.3rem;
align-items: flex-start;
align-self: stretch;
margin-top: 1.3rem;
`;
47 changes: 17 additions & 30 deletions src/components/targetArea/TargetArea.tsx
Original file line number Diff line number Diff line change
@@ -1,42 +1,29 @@
import styled from '@emotion/styled';
import { useState } from 'react';
import { Droppable } from 'react-beautiful-dnd';

import TargetAreaDate from './TargetAreaDate';
import TargetControlSection from './TargetControlSection';
import TargetTaskSection from './TargetTaskSection';

import { TaskType } from '@/types/tasks/taskType';
import { TargetControlSectionProps } from '@/types/today/TargetControlSectionProps';

interface TargetAreaProps {
interface TargetAreaProps extends TargetControlSectionProps {
handleSelectedTarget: (task: TaskType | null) => void;
selectedTarget: TaskType | null;
tasks: TaskType[];
}

function TargetArea({ handleSelectedTarget, selectedTarget }: TargetAreaProps) {
const [targetDate, setTargetDate] = useState(new Date());

const handlePrevBtn = () => {
const newDate = new Date(targetDate);
newDate.setDate(newDate.getDate() - 1);
setTargetDate(newDate);
};

const handleNextBtn = () => {
const newDate = new Date(targetDate);
newDate.setDate(newDate.getDate() + 1);
setTargetDate(newDate);
};

const handleTodayBtn = () => {
setTargetDate(new Date());
};

const handleChangeDate = (target: Date) => {
setTargetDate(target);
};

function TargetArea({
handleSelectedTarget,
selectedTarget,
tasks,
onClickPrevDate,
onClickNextDate,
onClickTodayDate,
onClickDatePicker,
targetDate,
}: TargetAreaProps) {
return (
<TargetAreaLayout>
{/* 날짜 */}
Expand All @@ -46,10 +33,10 @@ function TargetArea({ handleSelectedTarget, selectedTarget }: TargetAreaProps) {

{/* 버튼 */}
<TargetControlSection
onClickPrevDate={handlePrevBtn}
onClickNextDate={handleNextBtn}
onClickTodayDate={handleTodayBtn}
onClickDatePicker={handleChangeDate}
onClickPrevDate={onClickPrevDate}
onClickNextDate={onClickNextDate}
onClickTodayDate={onClickTodayDate}
onClickDatePicker={onClickDatePicker}
targetDate={targetDate}
/>
{/* 태스크 목록 */}
Expand All @@ -59,7 +46,7 @@ function TargetArea({ handleSelectedTarget, selectedTarget }: TargetAreaProps) {
<TargetTaskSection
handleSelectedTarget={handleSelectedTarget}
selectedTarget={selectedTarget}
selectedDate={targetDate}
tasks={tasks}
/>
{provided.placeholder}
</div>
Expand Down
3 changes: 3 additions & 0 deletions src/components/targetArea/TargetAreaDate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@ import formatDatetoStrinKor from '@/utils/formatDatetoStringKor';
interface TargetAreaDateProps {
targetDate: Date;
}

function TargetAreaDate({ targetDate }: TargetAreaDateProps) {
const formatDate = formatDatetoStrinKor(targetDate);
return <DateText>{formatDate}</DateText>;
}

const DateText = styled.h2`
${({ theme }) => theme.fontTheme.HEADLINE_02};
padding: 0.7rem 0.2rem 0.7rem 1rem;
`;

export default TargetAreaDate;
9 changes: 1 addition & 8 deletions src/components/targetArea/TargetControlSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,9 @@ import TextBtn from '@/components/common/button/textBtn/TextBtn';
import DateCorrectionModal from '@/components/common/datePicker/DateCorrectionModal';
import ModalBackdrop from '@/components/common/modal/ModalBackdrop';
import MODAL from '@/constants/modalLocation';
import { TargetControlSectionProps } from '@/types/today/TargetControlSectionProps';
import formatDatetoString from '@/utils/formatDatetoString';

interface TargetControlSectionProps {
onClickPrevDate: () => void;
onClickNextDate: () => void;
onClickTodayDate: () => void;
onClickDatePicker: (target: Date) => void;
targetDate: Date;
}

function TargetControlSection({
onClickPrevDate,
onClickNextDate,
Expand Down
13 changes: 5 additions & 8 deletions src/components/targetArea/TargetTaskSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,25 @@ import BtnTask from '../common/BtnTask/BtnTask';
import BtnTaskContainer from '../common/BtnTaskContainer';
import EmptyContainer from '../common/EmptyContainer';

import useGetTasks from '@/apis/tasks/getTask/query';
import { TaskType } from '@/types/tasks/taskType';
import formatDatetoLocalDate from '@/utils/formatDatetoLocalDate';

interface TargetTaskSectionProps {
handleSelectedTarget: (task: TaskType | null) => void;
selectedTarget: TaskType | null;
selectedDate: Date | null;
tasks: TaskType[];
}
function TargetTaskSection(props: TargetTaskSectionProps) {
const { handleSelectedTarget, selectedTarget, selectedDate } = props;
const targetDate = formatDatetoLocalDate(selectedDate);
const { data } = useGetTasks({ targetDate });
const { handleSelectedTarget, selectedTarget, tasks } = props;

return (
<BtnTaskContainer type="target">
{data.data.tasks.length === 0 ? (
{tasks.length === 0 ? (
<EmptyLayout>
<EmptyContainer />
</EmptyLayout>
) : (
<>
{data.data.tasks.map((task: TaskType, index: number) => (
{tasks.map((task: TaskType, index: number) => (
<Draggable key={task.id} draggableId={task.id.toString()} index={index}>
{(provided, snapshot) => (
<div
Expand Down
Loading
Loading