Skip to content

Commit

Permalink
Feat: #63 할일 등록 모달 상태 설정 기능 추가 (#70)
Browse files Browse the repository at this point in the history
* Refactor: #63 useStatusQuery 검색 방식 변경에 따른 구조 변경

* Fix: #63 prettier 재반영

* Feat: #63 할일 상태 선택 기능 추가
  • Loading branch information
Seok93 authored Aug 11, 2024
1 parent 1b55376 commit 9d61295
Show file tree
Hide file tree
Showing 13 changed files with 153 additions and 93 deletions.
10 changes: 5 additions & 5 deletions src/components/common/ToggleButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ export default function ToggleButton({ id, checked, onChange: handleChange }: To
/>
{/* prettier-ignore */}
<span className="
absolute bottom-0 left-0 right-0 top-0 cursor-pointer rounded-full bg-disable transition duration-300
before:content-[''] before:absolute before:left-2 before:top-1/2 before:-translate-y-1/2 before:size-7
before:rounded-full before:bg-white before:transition before:duration-300
peer-checked:bg-main peer-checked:before:translate-x-9
"/>
absolute bottom-0 left-0 right-0 top-0 cursor-pointer rounded-full bg-disable transition duration-300
before:content-[''] before:absolute before:left-2 before:top-1/2 before:-translate-y-1/2 before:size-7
before:rounded-full before:bg-white before:transition before:duration-300
peer-checked:bg-main peer-checked:before:translate-x-9
"/>
</label>
);
}
11 changes: 7 additions & 4 deletions src/components/modal/project-status/CreateModalProjectStatus.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import { SubmitHandler } from 'react-hook-form';
import ModalLayout from '@layouts/ModalLayout';
import ModalPortal from '@components/modal/ModalPortal';
import ModalProjectStatusForm from '@components/modal/project-status/ModalProjectStatusForm';
import ModalFormButton from '@components/modal/ModalFormButton';
import { ProjectStatusForm } from '@/types/ProjectStatusType';

import type { SubmitHandler } from 'react-hook-form';
import type { Project } from '@/types/ProjectType';
import type { ProjectStatusForm } from '@/types/ProjectStatusType';

type CreateModalProjectStatusProps = {
project: Project;
onClose: () => void;
};

export default function CreateModalProjectStatus({ onClose: handleClose }: CreateModalProjectStatusProps) {
export default function CreateModalProjectStatus({ project, onClose: handleClose }: CreateModalProjectStatusProps) {
// ToDo: 상태 생성을 위한 네트워크 로직 추가
const handleSubmit: SubmitHandler<ProjectStatusForm> = async (data) => {
console.log('생성 폼 제출');
Expand All @@ -19,7 +22,7 @@ export default function CreateModalProjectStatus({ onClose: handleClose }: Creat
return (
<ModalPortal>
<ModalLayout onClose={handleClose}>
<ModalProjectStatusForm formId="createStatusForm" onSubmit={handleSubmit} />
<ModalProjectStatusForm formId="createStatusForm" project={project} onSubmit={handleSubmit} />
<ModalFormButton formId="createStatusForm" isCreate onClose={handleClose} />
</ModalLayout>
</ModalPortal>
Expand Down
22 changes: 12 additions & 10 deletions src/components/modal/project-status/ModalProjectStatusForm.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,38 @@
import { SubmitHandler, useForm } from 'react-hook-form';
import { useForm } from 'react-hook-form';
import { RiProhibited2Fill } from 'react-icons/ri';
import { STATUS_VALIDATION_RULES } from '@constants/formValidationRules';
import useProjectStatusQuery from '@hooks/query/useProjectStatusQuery';
import DuplicationCheckInput from '@components/common/DuplicationCheckInput';
import { RiProhibited2Fill } from 'react-icons/ri';
import useStatusQuery from '@hooks/query/useStatusQuery';

import type { SubmitHandler } from 'react-hook-form';
import type { ProjectStatus, ProjectStatusForm } from '@/types/ProjectStatusType';
import type { Project } from '@/types/ProjectType';

type ModalProjectStatusFormProps = {
formId: string;
project: Project;
statusId?: ProjectStatus['statusId'];
onSubmit: SubmitHandler<ProjectStatusForm>;
};

export default function ModalProjectStatusForm({ formId, statusId, onSubmit }: ModalProjectStatusFormProps) {
const { initialValue, nameList, colorList, usableColorList } = useProjectStatusQuery(statusId);
export default function ModalProjectStatusForm({ formId, project, statusId, onSubmit }: ModalProjectStatusFormProps) {
const { initialValue, nameList, colorList, usableColorList } = useStatusQuery(project.projectId, statusId);
const {
register,
watch,
handleSubmit,
formState: { errors },
} = useForm<ProjectStatusForm>({
mode: 'onChange',
defaultValues: initialValue || { name: '', color: '' },
defaultValues: initialValue,
});
const statusName = watch('name');
const selectedColor = watch('color');

return (
<form id={formId} className="mb-10 flex grow flex-col justify-center" onSubmit={handleSubmit(onSubmit)}>
<DuplicationCheckInput
id="name"
label="상태명"
value={statusName}
value={watch('name')}
placeholder="상태명을 입력하세요."
errors={errors.name?.message}
register={register('name', STATUS_VALIDATION_RULES.STATUS_NAME(nameList))}
Expand All @@ -42,7 +44,7 @@ export default function ModalProjectStatusForm({ formId, statusId, onSubmit }: M
<label
htmlFor={color}
style={{ backgroundColor: color }}
className={`realative inline-block size-20 cursor-pointer rounded-full ${isUsable && selectedColor === color ? 'border-4 border-selected' : ''}`}
className={`inline-block size-20 cursor-pointer rounded-full ${isUsable && watch('color') === color ? 'border-4 border-selected' : ''}`}
>
<input
type="radio"
Expand Down
20 changes: 16 additions & 4 deletions src/components/modal/project-status/UpdateModalProjectStatus.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
import { SubmitHandler } from 'react-hook-form';
import ModalLayout from '@layouts/ModalLayout';
import ModalPortal from '@components/modal/ModalPortal';
import ModalProjectStatusForm from '@components/modal/project-status/ModalProjectStatusForm';
import ModalFormButton from '@components/modal/ModalFormButton';
import { ProjectStatus, ProjectStatusForm } from '@/types/ProjectStatusType';

import type { SubmitHandler } from 'react-hook-form';
import type { Project } from '@/types/ProjectType';
import type { ProjectStatus, ProjectStatusForm } from '@/types/ProjectStatusType';

type UpdateModalProjectStatusProps = {
project: Project;
statusId: ProjectStatus['statusId'];
onClose: () => void;
};

export default function UpdateModalProjectStatus({ statusId, onClose: handleClose }: UpdateModalProjectStatusProps) {
export default function UpdateModalProjectStatus({
project,
statusId,
onClose: handleClose,
}: UpdateModalProjectStatusProps) {
// ToDo: 상태 수정을 위한 네트워크 로직 추가
const handleSubmit: SubmitHandler<ProjectStatusForm> = async (data) => {
console.log(statusId, '수정 폼 제출');
Expand All @@ -21,7 +28,12 @@ export default function UpdateModalProjectStatus({ statusId, onClose: handleClos
return (
<ModalPortal>
<ModalLayout onClose={handleClose}>
<ModalProjectStatusForm formId="updateStatusForm" statusId={statusId} onSubmit={handleSubmit} />
<ModalProjectStatusForm
formId="updateStatusForm"
project={project}
statusId={statusId}
onSubmit={handleSubmit}
/>
<ModalFormButton formId="updateStatusForm" isCreate={false} onClose={handleClose} />
</ModalLayout>
</ModalPortal>
Expand Down
7 changes: 4 additions & 3 deletions src/components/modal/task/CreateModalTask.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { SubmitHandler } from 'react-hook-form';
import ModalLayout from '@layouts/ModalLayout';
import ModalPortal from '@components/modal/ModalPortal';
import ModalTaskForm from '@components/modal/task/ModalTaskForm';
import ModalFormButton from '@components/modal/ModalFormButton';
import { TaskForm } from '@/types/TaskType';
import { Project } from '@/types/ProjectType';

import type { SubmitHandler } from 'react-hook-form';
import type { TaskForm } from '@/types/TaskType';
import type { Project } from '@/types/ProjectType';

type CreateModalTaskProps = {
project: Project;
Expand Down
41 changes: 38 additions & 3 deletions src/components/modal/task/ModalTaskForm.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { useState } from 'react';
import { DateTime } from 'luxon';
import { IoSearch } from 'react-icons/io5';
import { SubmitHandler, useForm } from 'react-hook-form';
import { useForm } from 'react-hook-form';
import { TASK_VALIDATION_RULES } from '@constants/formValidationRules';
import ToggleButton from '@components/common/ToggleButton';
import DuplicationCheckInput from '@components/common/DuplicationCheckInput';
import useTaskQuery from '@hooks/query/useTaskQuery';
import { Project } from '@/types/ProjectType';
import { Task, TaskForm } from '@/types/TaskType';
import useStatusQuery from '@hooks/query/useStatusQuery';

import type { SubmitHandler } from 'react-hook-form';
import type { Project } from '@/types/ProjectType';
import type { Task, TaskForm } from '@/types/TaskType';

type ModalTaskFormProps = {
formId: string;
Expand All @@ -18,7 +21,9 @@ type ModalTaskFormProps = {

export default function ModalTaskForm({ formId, project, taskId, onSubmit }: ModalTaskFormProps) {
const [hasDeadline, setHasDeadline] = useState(false);
const { statusList } = useStatusQuery(project.projectId, taskId);
const { taskNameList } = useTaskQuery(project.projectId);
// ToDo: 상태 수정 모달 작성시 기본값 설정 방식 변경할 것
const {
register,
watch,
Expand All @@ -34,6 +39,7 @@ export default function ModalTaskForm({ formId, project, taskId, onSubmit }: Mod
content: '',
startDate: DateTime.fromJSDate(new Date()).toFormat('yyyy-LL-dd'),
endDate: DateTime.fromJSDate(new Date()).toFormat('yyyy-LL-dd'),
statusId: statusList[0].statusId,
},
});

Expand All @@ -49,6 +55,35 @@ export default function ModalTaskForm({ formId, project, taskId, onSubmit }: Mod
className="mb-20 flex w-4/5 max-w-375 grow flex-col justify-center"
onSubmit={handleSubmit(onSubmit)}
>
{/* ToDo: 상태 선택 리팩토링 할 것 */}
<div className="flex items-center justify-start gap-4">
{statusList.map((status) => {
const { statusId, name, color } = status;
const isChecked = +watch('statusId') === statusId;
return (
<label
key={statusId}
htmlFor={name}
className={`flex items-center rounded-lg border px-5 py-3 text-emphasis ${isChecked ? 'border-input bg-white' : 'bg-button'}`}
>
<input
id={name}
type="radio"
className="invisible h-0 w-0"
value={statusId}
checked={isChecked}
{...register('statusId', TASK_VALIDATION_RULES.STATUS)}
/>
<div style={{ borderColor: color }} className="mr-3 h-8 w-8 rounded-full border" />
<h3 className="text-xs">{name}</h3>
</label>
);
})}
</div>
<div className={`my-5 h-10 grow text-xs text-error ${errors.statusId ? 'visible' : 'invisible'}`}>
{errors.statusId?.message}
</div>

<DuplicationCheckInput
id="name"
label="일정"
Expand Down
7 changes: 4 additions & 3 deletions src/components/modal/task/UpdateModalTask.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { SubmitHandler } from 'react-hook-form';
import ModalLayout from '@layouts/ModalLayout';
import ModalPortal from '@components/modal/ModalPortal';
import ModalTaskForm from '@components/modal/task/ModalTaskForm';
import ModalFormButton from '@components/modal/ModalFormButton';
import { Task, TaskForm } from '@/types/TaskType';
import { Project } from '@/types/ProjectType';

import type { SubmitHandler } from 'react-hook-form';
import type { Project } from '@/types/ProjectType';
import type { Task, TaskForm } from '@/types/TaskType';

type UpdateModalTaskProps = {
project: Project;
Expand Down
4 changes: 3 additions & 1 deletion src/components/task/kanban/ProjectStatusContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useMemo } from 'react';
import { Draggable } from '@hello-pangea/dnd';
import useModal from '@hooks/useModal';
import useProjectContext from '@hooks/useProjectContext';
import TaskItemList from '@components/task/kanban/TaskItemList';
import UpdateModalProjectStatus from '@components/modal/project-status/UpdateModalProjectStatus';
import { generatePrefixId } from '@utils/converter';
Expand All @@ -13,6 +14,7 @@ type TaskStatusContainerProps = {
};

export default function TaskStatusContainer({ statusTask }: TaskStatusContainerProps) {
const { project } = useProjectContext();
const { showModal, openModal, closeModal } = useModal();
const { statusId, name, color, order, tasks } = statusTask;
const draggableId = useMemo(() => generatePrefixId(statusId, DND_DRAGGABLE_PREFIX.STATUS), [statusId]);
Expand Down Expand Up @@ -40,7 +42,7 @@ export default function TaskStatusContainer({ statusTask }: TaskStatusContainerP
</article>
)}
</Draggable>
{showModal && <UpdateModalProjectStatus onClose={closeModal} statusId={statusTask.statusId} />}
{showModal && <UpdateModalProjectStatus project={project} statusId={statusTask.statusId} onClose={closeModal} />}
</>
);
}
8 changes: 6 additions & 2 deletions src/constants/formValidationRules.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import Validator from '@utils/Validator';
import { deepFreeze } from '@utils/deepFreeze';
import { EMAIL_REGEX, ID_REGEX, NICKNAME_REGEX, PASSWORD_REGEX, PHONE_REGEX } from '@constants/regex';
import { Project } from '@/types/ProjectType';
import { Task } from '@/types/TaskType';

import type { Project } from '@/types/ProjectType';
import type { Task } from '@/types/TaskType';

type ValidateOption = { [key: string]: (value: string) => string | boolean };

Expand Down Expand Up @@ -121,6 +122,9 @@ export const STATUS_VALIDATION_RULES = deepFreeze({
});

export const TASK_VALIDATION_RULES = deepFreeze({
STATUS: {
required: '상태를 선택해주세요.',
},
TASK_NAME: (nameList: string[]) => ({
required: '일정명을 입력해주세요.',
maxLength: {
Expand Down
57 changes: 0 additions & 57 deletions src/hooks/query/useProjectStatusQuery.ts

This file was deleted.

Loading

0 comments on commit 9d61295

Please sign in to comment.