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: #63 할일 등록 모달 상태 설정 기능 추가 #70

Merged
merged 14 commits into from
Aug 11, 2024
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
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