diff --git a/src/components/ModalTags.tsx b/src/components/ModalTags.tsx index 5adbf6e..b583f55 100644 --- a/src/components/ModalTags.tsx +++ b/src/components/ModalTags.tsx @@ -1,4 +1,4 @@ -import { IAPITag } from "@/pages/profile_tasks.dto"; +import { IAPITag, IViewTagsResponse } from "@/pages/profile_tasks.dto"; import apiClient from "@/services/api"; import { cn } from "@/utils/class-merge"; import { BookOpenIcon, CheckIcon, DocumentDuplicateIcon, PlusCircleIcon } from "@heroicons/react/24/outline"; @@ -25,7 +25,7 @@ interface ModalTagsProps extends ModalWindowProps { first: IAPITag[]; second: IAPITag[]; }; - refreshTags: () => void; + refreshTags: () => Promise; } const ModalTags: FunctionComponent = ({ @@ -64,7 +64,7 @@ const ModalTags: FunctionComponent = ({ { method: "POST", body: JSON.stringify(data) } ); if (response.success) { - refreshTags(); + await refreshTags(); if (showAddFirstTag) { const new_subject_id = response.subject!.id; onChange!((prev) => ({ ...prev, first: new_subject_id })); @@ -89,7 +89,7 @@ const ModalTags: FunctionComponent = ({ body: JSON.stringify(data), }); if (!response.error) { - refreshTags(); + await refreshTags(); } else { setShowErrorDialog(true); const match = response.error?.match(/\[(.+)\]/); diff --git a/src/pages/profile_calendar.tsx b/src/pages/profile_calendar.tsx index dc828eb..ab19252 100644 --- a/src/pages/profile_calendar.tsx +++ b/src/pages/profile_calendar.tsx @@ -80,16 +80,7 @@ const ProfileCalendar: FunctionComponent = () => { setError, formState: { errors }, } = useForm({ - defaultValues: { - subject: { - name: "", - id: 0, - }, - taskType: { - name: "", - id: 0, - }, - }, + defaultValues: {}, }); useEffect(() => { @@ -146,13 +137,13 @@ const ProfileCalendar: FunctionComponent = () => { return; } if ((!editContent?.subject.id || !editContent.taskType.id) && (!tags.first || !tags.second)) { - setError("subject", { message: "Выберите теги" }); + setError("date", { message: "Выберите теги" }); return; } try { - const selectedSubject = editContent?.subject.id || tags.first; - const selectedTaskType = editContent?.taskType.id || tags.second; + const selectedSubject = tags.first || editContent?.subject.id; + const selectedTaskType = tags.second || editContent?.taskType.id; // Format date to DD-MM-YYYYTHH:MM const formattedDate = calendarDate @@ -171,8 +162,8 @@ const ProfileCalendar: FunctionComponent = () => { const taskData = { title: data.name, description: data.description || "", - subject: selectedSubject, - taskType: selectedTaskType, + subject_id: selectedSubject, + taskType_id: selectedTaskType, dateTime_due: formattedDate, telegram_notifications: false, priority: selectedPriority, @@ -195,7 +186,17 @@ const ProfileCalendar: FunctionComponent = () => { if (!response.success) { throw new Error(response.message); - } + } else if (isEdit) + setEditContent({ + name: response.task.title, + id: response.task.id.toString(), + description: response.task.description, + priority: response.task.priority, + checked: response.task.isCompleted, + subject: response.task.subject, + taskType: response.task.task_type, + date: new Date(response.task.dateTime_due), + }); } await fetchTasks(); @@ -374,35 +375,9 @@ const ProfileCalendar: FunctionComponent = () => { month: { className: calendarStyles.month }, year: { className: calendarStyles.year }, }; - if (isLoading) - return ( -
-
Загрузка...
; -
- ); return (
- { - setTags({ first: 0, second: 0, overdue: false }); - }} - onChange={setTags} - /> - { - if (isEdit && !isEditModal) setCalendarDate(null); - }} - onChange={(e) => isEditModal && setCalendarDate(e.value)} - value={calendarDate!} - /> { {errors.name &&

{errors.name.message}

} {errors.description &&

{errors.description.message}

} {errors.date &&

{errors.date.message}

} - {errors.subject &&

{errors.subject.message}

}
{ )} - -

"Вы уверены, что хотите удалить эту задачу?"

-
- setCurrentDate(e ? e.value! : new Date())} - inline - pt={pt} - dateTemplate={dateTemplate} - className="[&_.p-datepicker]:!border-0 [&_.p-datepicker-calendar]:border-separate [&_.p-datepicker-calendar]:border-spacing-2 [&_td]:rounded-lg [&_td]:border [&_td]:border-[rgba(251,194,199,0.38)]" - /> + {isLoading ? ( +
Загрузка...
+ ) : ( + <> + { + setTags({ first: 0, second: 0, overdue: false }); + }} + onChange={setTags} + /> + { + if (isEdit && !isEditModal) setCalendarDate(null); + }} + onChange={(e) => isEditModal && setCalendarDate(e.value)} + value={calendarDate!} + /> + +

"Вы уверены, что хотите удалить эту задачу?"

+
+ setCurrentDate(e ? e.value! : new Date())} + inline + pt={pt} + dateTemplate={dateTemplate} + className="[&_.p-datepicker]:!border-0 [&_.p-datepicker-calendar]:border-separate [&_.p-datepicker-calendar]:border-spacing-2 [&_td]:rounded-lg [&_td]:border [&_td]:border-[rgba(251,194,199,0.38)]" + /> -
-

Задачи на {formatDate(currentDate)}

- {selectedTasks.length > 0 ? ( -
- {selectedTasks.map((task) => ( - handleViewTask(task.id)} - onMarkClick={() => handleTaskCheck(task.id)} - /> - ))} +
+

Задачи на {formatDate(currentDate)}

+ {selectedTasks.length > 0 ? ( +
+ {selectedTasks.map((task) => ( + handleViewTask(task.id)} + onMarkClick={() => handleTaskCheck(task.id)} + /> + ))} +
+ ) : ( +
На этот день задач нет
+ )}
- ) : ( -
На этот день задач нет
- )} -
+ + )}
); }; diff --git a/src/pages/profile_tasks.dto.ts b/src/pages/profile_tasks.dto.ts index 4d29b62..026d2e7 100644 --- a/src/pages/profile_tasks.dto.ts +++ b/src/pages/profile_tasks.dto.ts @@ -17,7 +17,7 @@ export interface ITaskView extends Omit { task_type: IAPITag; } -export interface ITaskForm extends Omit { +export interface ITaskForm extends Omit { date: string; } @@ -80,15 +80,11 @@ export interface IEditTaskResponse { id: number; title: string; description: string; - subject: string; - taskType: string; + subject: IAPITag; + task_type: IAPITag; dateTime_due: string; isCompleted: boolean; - reminder?: { - remind_before_days: number; - repeat_interval: number; - reminder_time: string; - }; + priority: number; }; } diff --git a/src/pages/profile_tasks.tsx b/src/pages/profile_tasks.tsx index b70b1b3..c75abc2 100644 --- a/src/pages/profile_tasks.tsx +++ b/src/pages/profile_tasks.tsx @@ -32,7 +32,6 @@ import { Dropdown } from "primereact/dropdown"; import { SelectItem } from "primereact/selectitem"; import { Nullable } from "primereact/ts-helpers"; import { SubmitHandler, useForm } from "react-hook-form"; -import { v4 as uuid } from "uuid"; import { IApiResponse, IAPITag, @@ -87,7 +86,7 @@ const ProfileTasks: FunctionComponent = () => { fetchTags(); }, []); - const fetchTags = async () => { + const fetchTags = async (): Promise => { try { const response = await apiClient("/api/tags/view_tags/"); setSubjectChoices(response.subjects); @@ -126,18 +125,7 @@ const ProfileTasks: FunctionComponent = () => { reset, setError, formState: { errors }, - } = useForm({ - defaultValues: { - subject: { - name: "", - id: 0, - }, - taskType: { - name: "", - id: 0, - }, - }, - }); + } = useForm({}); const example_tags = useMemo( () => ({ @@ -153,7 +141,7 @@ const ProfileTasks: FunctionComponent = () => { return; } if ((!editContent?.subject.id || !editContent.taskType.id) && (!tags.first || !tags.second)) { - setError("subject", { message: "Выберите теги" }); + setError("date", { message: "Выберите теги" }); return; } @@ -202,11 +190,20 @@ const ProfileTasks: FunctionComponent = () => { if (!response.success) { throw new Error(response.message); - } + } else if (isEdit) + setEditContent({ + name: response.task.title, + id: response.task.id.toString(), + description: response.task.description, + priority: response.task.priority, + checked: response.task.isCompleted, + subject: response.task.subject, + taskType: response.task.task_type, + date: new Date(response.task.dateTime_due), + }); } await fetchTasks(); - if (isCreating) setIsOpen(false); setTags({ first: 0, second: 0, overdue: false }); } catch (error) { @@ -223,14 +220,6 @@ const ProfileTasks: FunctionComponent = () => { name: "", description: "", date: "", - subject: { - name: "", - id: 0, - }, - taskType: { - name: "", - id: 0, - }, priority: 4, checked: false, }); @@ -385,37 +374,8 @@ const ProfileTasks: FunctionComponent = () => { } }; - if (isLoading) - return ( -
-
Загрузка...
; -
- ); - return (
- { - if (!isCreating) setTags({ first: 0, second: 0, overdue: false }); - }} - onChange={setTags} - /> - { - if (isEdit && !isEditModal) setCalendarDate(null); - }} - onChange={(e) => (isCreating || isEditModal) && setCalendarDate(e.value)} - value={calendarDate!} - /> { {errors.name &&

{errors.name.message}

} {errors.description &&

{errors.description.message}

} {errors.date &&

{errors.date.message}

} - {errors.subject &&

{errors.subject.message}

}
{ year: "numeric", hour: "2-digit", minute: "2-digit", - }).format(calendarDate!)} + }).format(calendarDate ?? editContent.date)}

{ class="flex h-full w-full flex-col items-start justify-between" onSubmit={(e) => { e.preventDefault(); - handleSubmit((data) => saveTask({ ...data, id: uuid() }))(); + handleSubmit((data) => saveTask(data))(); }} >
@@ -609,7 +568,6 @@ const ProfileTasks: FunctionComponent = () => {
{errors.name &&

{errors.name.message}

} {errors.date &&

{errors.date.message}

} - {errors.subject?.message &&

{errors.subject.message}

}
+ )} +
+
)} -
- )} -
-
{ - setIsCreating(true); - setIsOpen(true); - }} - > - -
- {tasks.length > 0 && ( - - )} -
- {openSearchModal && ( -
- {/* Пофиксить разфокус при вводе */} -
- - { - setSearchQuery((e.target as HTMLInputElement).value); - }} - /> - { - setSearchQuery(""); - setOpenSearchModal(false); - }} - /> -
-
- )} - {openFilterModal && ( -
-
-
Фильтры
-
-
- { - setFilterTags({ ...filterTags, overdue: e.target.checked! }); - }} - pt={{ - root: { - className: cn("cursor-pointer inline-flex relative select-none align-bottom", "w-6 h-6"), - }, - input: { - className: cn( - "absolute appearance-none top-0 left-0 size-full p-0 m-0 opacity-0 z-10 outline-none cursor-pointer" - ), - }, - box: ({ props, context }: CheckboxPassThroughMethodOptions) => ({ - className: cn( - "flex items-center justify-center", - "border-2 w-6 h-6 text-gray-600 rounded-lg transition-colors duration-200", - { - "border-gray-300 bg-white": !context.checked, - "border-blue-500 bg-blue-500": context.checked, - }, - { - "hover:border-blue-500 focus:outline-none focus:outline-offset-0 focus:shadow-[0_0_0_0.2rem_rgba(191,219,254,1)]": - !props.disabled, - "cursor-default opacity-60": props.disabled, - } - ), - }), - icon: { - className: "w-4 h-4 transition-all duration-200 text-white text-base", - }, - }} - > - -
-
-
{ - setOpenFirstList(!openFirstList); - setOpenSecondList(false); - }} - > - - {subjectChoices.find((s) => s.id === filterTags.first)?.name || "Предмет"} -
- {openFirstList && ( -
- {example_tags.first.map((tag) => { - return ( -
{ - setFilterTags({ ...filterTags, first: tag.id }); - setOpenFirstList(false); - }} - > -
- {filterTags.first === tag.id &&
} -
- {tag.name} -
- ); - })} -
- )} -
- -
-
{ - setOpenSecondList(!openSecondList); - setOpenFirstList(false); - }} - > - - {taskTypeChoices.find((s) => s.id === filterTags.second)?.name || "Задача"} -
- {openSecondList && ( -
- {example_tags.second.map((tag) => ( -
{ - setFilterTags({ ...filterTags, second: tag.id }); - setOpenSecondList(false); - }} - > -
- {filterTags.second === tag.id &&
} -
- {tag.name} -
- ))} -
- )} -
- - {(filterTags.first || filterTags.second || filterTags.overdue) && ( - - )} -
-
-
+ )}
);