Skip to content

Commit

Permalink
Добавляет возможность изменения задачи
Browse files Browse the repository at this point in the history
  • Loading branch information
Seasle committed Dec 30, 2023
1 parent 7bb67a4 commit 59dd67d
Show file tree
Hide file tree
Showing 18 changed files with 145 additions and 39 deletions.
3 changes: 2 additions & 1 deletion src/app/providers/ModalProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { type PropsWithChildren } from 'react';
import { ModalsProvider } from '@mantine/modals';
import { TaskCreateForm } from '@/entities/task';
import { TaskCreateForm, TaskEditForm } from '@/features/task';

export const ModalProvider = ({ children }: PropsWithChildren<unknown>) => {
return (
<ModalsProvider
modals={{
createTask: TaskCreateForm,
editTask: TaskEditForm,
}}
>
{children}
Expand Down
19 changes: 19 additions & 0 deletions src/entities/task/model/tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import { type TaskBase, type Task, type TaskId } from '@/shared/types';

const addTask = createEvent<TaskBase>();

const modifyTask = createEvent<{ id: TaskId } & TaskBase>();

const removeTask = createEvent<TaskId>();

const toggleTask = createEvent<TaskId>();
Expand Down Expand Up @@ -48,6 +50,22 @@ export const $tasks = createStore<Record<TaskId, Task>>({})
},
};
})
.on(modifyTask, (store, { id, ...taskBase }) => {
const title = taskBase.title.trim();
const description = taskBase.description ? taskBase.description : undefined;
const expiresIn = taskBase.expiresIn ?? undefined;

return {
...store,
[id]: {
...store[id],
title,
description,
priority: taskBase.priority,
expiresIn,
},
};
})
.on(removeTask, (store, taskId) => excludeKey(store, taskId))
.on(toggleTask, (store, taskId) => {
const isCompleted = !store[taskId].isCompleted;
Expand Down Expand Up @@ -115,6 +133,7 @@ const useTask = (id?: TaskId) => {

export const events = {
addTask,
modifyTask,
removeTask,
toggleTask,
markTaskToRemove,
Expand Down
2 changes: 1 addition & 1 deletion src/entities/task/ui/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ export * from './task-non-overdue-icon';
export * from './task-priority-icon';
export * from './task-progress';
export * from './task-delete-button';
export * from './task-create-form';
export * from './task-form';
22 changes: 11 additions & 11 deletions src/entities/task/ui/task-card/ui/TaskCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,7 @@ export const TaskCard = ({ task }: TaskCardProps) => {
{task.title}
</Text>
</Group>
<Group>
<TaskPriorityIcon variant={task.priority} />
<TaskDeleteButton task={task} />
</Group>
<TaskPriorityIcon variant={task.priority} />
</Flex>
{task.description && <Text size="sm">{task.description}</Text>}
{task.expiresIn && (
Expand All @@ -60,13 +57,16 @@ export const TaskCard = ({ task }: TaskCardProps) => {
<Text size="xs">Сделана {humanizedDate(task.completedIn)}</Text>
)}
</Group>
<Button
size="xs"
color={task.isCompleted ? 'red' : 'green'}
onClick={onToggleClick}
>
{task.isCompleted ? 'Переоткрыть' : 'Завершить'}
</Button>
<Group>
<TaskDeleteButton task={task} />
<Button
size="xs"
color={task.isCompleted ? 'red' : 'green'}
onClick={onToggleClick}
>
{task.isCompleted ? 'Переоткрыть' : 'Завершить'}
</Button>
</Group>
</Flex>
</Stack>
</Paper>
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -11,31 +11,36 @@ import {
} from '@mantine/core';
import { DateInput } from '@mantine/dates';
import { useForm } from '@mantine/form';
import { type ContextModalProps } from '@mantine/modals';
import { IconCheck } from '@tabler/icons-react';
import { taskModel } from '@/entities/task';
import { priorityValues } from '../const';
import { ChoiceItem } from '@/shared/ui';
import { useDelayedKeyOnResize } from '@/shared/hooks';
import { type TaskPriority } from '@/shared/types';
import { type Task, type TaskPriority } from '@/shared/types';

interface TaskCreateFormValues {
const today = new Date();

export interface TaskFormValues {
title: string;
description: string;
priority: TaskPriority;
expiresIn: Date | null;
}

const today = new Date();
export interface TaskFormProps {
data?: Task | null;
submitText: string;
onSubmit: (values: TaskFormValues) => Promise<void>;
}

export const TaskCreateForm = ({ id, context }: ContextModalProps) => {
export const TaskForm = ({ data, submitText, onSubmit }: TaskFormProps) => {
const { ref, key } = useDelayedKeyOnResize(50);
const form = useForm<TaskCreateFormValues>({
const form = useForm<TaskFormValues>({
initialValues: {
title: '',
description: '',
priority: 'NORMAL',
expiresIn: null,
title: data?.title ?? '',
description: data?.description ?? '',
priority: data?.priority ?? 'NORMAL',
expiresIn:
data?.expiresIn !== undefined ? new Date(data.expiresIn) : null,
},
validate: {
title: (value) =>
Expand All @@ -45,27 +50,20 @@ export const TaskCreateForm = ({ id, context }: ContextModalProps) => {
const isSubmitting = useRef(false);

const onFormSubmit = useCallback(
(values: TaskCreateFormValues) => {
(values: TaskFormValues) => {
if (isSubmitting.current) {
return;
}

isSubmitting.current = true;

taskModel.events.addTask({
title: values.title,
description: values.description,
priority: values.priority,
expiresIn: values.expiresIn?.toISOString(),
});

context.closeContextModal(id);

window.requestIdleCallback(() => {
isSubmitting.current = false;
void onSubmit(values).finally(() => {
window.requestIdleCallback(() => {
isSubmitting.current = false;
});
});
},
[id, context],
[onSubmit],
);

return (
Expand Down Expand Up @@ -132,7 +130,7 @@ export const TaskCreateForm = ({ id, context }: ContextModalProps) => {
leftSection={<IconCheck />}
disabled={isSubmitting.current}
>
Создать
{submitText}
</Button>
</Center>
</Stack>
Expand Down
1 change: 1 addition & 0 deletions src/entities/task/ui/task-form/ui/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './TaskForm';
12 changes: 12 additions & 0 deletions src/entities/task/utils/modals.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { modals } from '@mantine/modals';
import { type TaskId } from '@/shared/types';

export const openCreateTaskModal = () =>
modals.openContextModal({
Expand All @@ -8,3 +9,14 @@ export const openCreateTaskModal = () =>
centered: true,
innerProps: {},
});

export const openEditTaskModal = (taskId: TaskId) =>
modals.openContextModal({
modal: 'editTask',
title: 'Редактирование задачи',
size: 'xl',
centered: true,
innerProps: {
taskId,
},
});
2 changes: 2 additions & 0 deletions src/features/task/ui/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export * from './tasks-filter';
export * from './filtered-tasks';
export * from './task-view';
export * from './task-create-form';
export * from './task-edit-form';
1 change: 1 addition & 0 deletions src/features/task/ui/task-create-form/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './ui';
24 changes: 24 additions & 0 deletions src/features/task/ui/task-create-form/ui/TaskCreateForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { useCallback } from 'react';
import { type ContextModalProps } from '@mantine/modals';
import { TaskForm, taskModel, type TaskFormValues } from '@/entities/task';

export const TaskCreateForm = ({ id, context }: ContextModalProps) => {
const onSubmit = useCallback(
(values: TaskFormValues) =>
new Promise<void>((resolve) => {
taskModel.events.addTask({
title: values.title,
description: values.description,
priority: values.priority,
expiresIn: values.expiresIn?.toISOString(),
});

context.closeContextModal(id);

resolve();
}),
[id, context],
);

return <TaskForm submitText="Создать" onSubmit={onSubmit} />;
};
1 change: 1 addition & 0 deletions src/features/task/ui/task-edit-form/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './ui';
36 changes: 36 additions & 0 deletions src/features/task/ui/task-edit-form/ui/TaskEditForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { useCallback } from 'react';
import { type ContextModalProps } from '@mantine/modals';
import { TaskForm, taskModel, type TaskFormValues } from '@/entities/task';
import { type TaskId } from '@/shared/types';

export interface TaskEditFormProps {
taskId: TaskId;
}

export const TaskEditForm = ({
id,
context,
innerProps: { taskId },
}: ContextModalProps<TaskEditFormProps>) => {
const task = taskModel.selectors.useTask(taskId);

const onSubmit = useCallback(
(values: TaskFormValues) =>
new Promise<void>((resolve) => {
taskModel.events.modifyTask({
id: taskId,
title: values.title,
description: values.description,
priority: values.priority,
expiresIn: values.expiresIn?.toISOString(),
});

context.closeContextModal(id);

resolve();
}),
[taskId, id, context],
);

return <TaskForm data={task} submitText="Изменить" onSubmit={onSubmit} />;
};
1 change: 1 addition & 0 deletions src/features/task/ui/task-edit-form/ui/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './TaskEditForm';
12 changes: 11 additions & 1 deletion src/widgets/task/ui/single-task/ui/SignleTask.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { SimpleGrid, Stack, Button } from '@mantine/core';
import { IconArrowLeft, IconEdit } from '@tabler/icons-react';
import { TaskView } from '@/features/task';
import { type TaskId } from '@/shared/types';
import { openEditTaskModal } from '@/entities/task';

export interface SingleTaskProps {
id?: TaskId;
Expand All @@ -15,6 +16,14 @@ export const SingleTask = ({ id }: SingleTaskProps) => {
navigate(-1);
};

const onEditClick = () => {
if (id === undefined) {
return;
}

openEditTaskModal(id);
};

return (
<Stack>
<SimpleGrid cols={2}>
Expand All @@ -31,7 +40,8 @@ export const SingleTask = ({ id }: SingleTaskProps) => {
variant="gradient"
gradient={{ from: 'green', to: 'cyan' }}
leftSection={<IconEdit />}
disabled
disabled={id === undefined}
onClick={onEditClick}
>
Изменить
</Button>
Expand Down

0 comments on commit 59dd67d

Please sign in to comment.