feat: create task form

This commit is contained in:
2025-04-23 16:09:41 +03:00
parent c1246939cd
commit b091e8d20d
2 changed files with 63 additions and 47 deletions

View File

@@ -31,14 +31,14 @@ const markStyle = tv({
const Task: FunctionComponent<TaskProps> = ({ name, checked = false, onClick = () => {} }: TaskProps) => { const Task: FunctionComponent<TaskProps> = ({ name, checked = false, onClick = () => {} }: TaskProps) => {
return ( return (
// Временное действие для тестирования // Временное действие для тестирования
<button onClick={onClick} class="w-[95%]"> <div class="w-[95%]">
<div class={classes.task}> <div class={classes.task} onClick={onClick}>
<div class={taskStyle({ checked })}> <div class={taskStyle({ checked })}>
<p class={markStyle({ checked })}></p> <p class={markStyle({ checked })}></p>
</div> </div>
{name} {name}
</div> </div>
</button> </div>
); );
}; };

View File

@@ -18,7 +18,7 @@ import {
PencilIcon, PencilIcon,
} from "@heroicons/react/24/outline"; } from "@heroicons/react/24/outline";
import { FunctionComponent } from "preact"; import { FunctionComponent } from "preact";
import { useEffect, useMemo, useRef, useState } from "preact/hooks"; import { useEffect, useMemo, useState } from "preact/hooks";
import { Nullable } from "primereact/ts-helpers"; import { Nullable } from "primereact/ts-helpers";
import { SubmitHandler, useForm } from "react-hook-form"; import { SubmitHandler, useForm } from "react-hook-form";
import { ITask, ITaskForm } from "./profile_tasks.dto"; import { ITask, ITaskForm } from "./profile_tasks.dto";
@@ -58,9 +58,7 @@ const ProfileTasks: FunctionComponent = () => {
const [isEditModal, setIsEditModal] = useState(false); // Включено редактирование задачи const [isEditModal, setIsEditModal] = useState(false); // Включено редактирование задачи
const [isCreating, setIsCreating] = useState(false); // Включено создание задачи const [isCreating, setIsCreating] = useState(false); // Включено создание задачи
const [editContent, setEditContent] = useState<ITask | null>(null); // Содержимое редактируемой задачи const [editContent, setEditContent] = useState<ITask | null>(null); // Содержимое редактируемой задачи
const taskNameRef = useRef<HTMLInputElement>(null); const [calendarDate, setCalendarDate] = useState<Nullable<Date>>(); // Выбранная в календаре дата
const taskDescriptionRef = useRef<HTMLTextAreaElement>(null);
const [calendarDate, setCalendarDate] = useState<Nullable<Date>>();
const getDate = useMemo(() => { const getDate = useMemo(() => {
const date = new Date(); const date = new Date();
const formatter = new Intl.DateTimeFormat("ru-RU", { month: "long", day: "numeric" }); const formatter = new Intl.DateTimeFormat("ru-RU", { month: "long", day: "numeric" });
@@ -81,17 +79,22 @@ const ProfileTasks: FunctionComponent = () => {
handleSubmit, handleSubmit,
register, register,
reset, reset,
setError,
formState: { errors }, formState: { errors },
} = useForm<ITaskForm>({ } = useForm<ITaskForm>({
defaultValues: { defaultValues: {
tags: [], tags: [],
}, },
}); });
const saveEdited: SubmitHandler<ITaskForm> = (data) => { const saveTask: SubmitHandler<ITaskForm> = (data) => {
if (!editContent) return; if (!calendarDate) {
const editedTask: ITask = { ...data, date: new Date(data.date) }; setError("date", { message: "Выберите дату" });
setTasks(tasks.map((task) => (task.id === editedTask.id ? editedTask : task))); return;
setIsEditModal(false); }
const eTask: ITask = { ...data, date: calendarDate };
if (isCreating) setTasks([...tasks, eTask]);
else setTasks(tasks.map((task) => (task.id === eTask.id ? eTask : task)));
if (isCreating) setIsOpen(false);
}; };
useEffect(() => { useEffect(() => {
if (editContent) reset({ ...editContent, date: editContent.date.toISOString().slice(0, 16) }); if (editContent) reset({ ...editContent, date: editContent.date.toISOString().slice(0, 16) });
@@ -100,6 +103,15 @@ const ProfileTasks: FunctionComponent = () => {
useEffect(() => { useEffect(() => {
if (calendarDate && editContent) setEditContent({ ...editContent, date: calendarDate }); if (calendarDate && editContent) setEditContent({ ...editContent, date: calendarDate });
}, [calendarDate]); }, [calendarDate]);
useEffect(() => {
reset({
name: "",
description: "",
date: "",
tags: ["Тег1", "Тег2"],
checked: false,
});
}, [isCreating]);
return ( return (
<div class={classes.container}> <div class={classes.container}>
<ModalCalendar <ModalCalendar
@@ -123,7 +135,14 @@ const ProfileTasks: FunctionComponent = () => {
}} }}
> >
{isEdit && editContent && ( {isEdit && editContent && (
<form class="flex h-full w-full flex-col items-start justify-between" onSubmit={(e) => e.preventDefault()}> <form
class="flex h-full w-full flex-col items-start justify-between"
onSubmit={(e) => {
e.preventDefault();
if (isEditModal) handleSubmit(saveTask)();
else setIsEditModal(!isEditModal);
}}
>
<div class="flex w-full flex-row items-start justify-between"> <div class="flex w-full flex-row items-start justify-between">
<div class="flex flex-1 flex-col gap-1 pe-2"> <div class="flex flex-1 flex-col gap-1 pe-2">
<input <input
@@ -154,8 +173,10 @@ const ProfileTasks: FunctionComponent = () => {
<div <div
className="flex cursor-pointer flex-col items-center gap-3" className="flex cursor-pointer flex-col items-center gap-3"
onClick={() => { onClick={() => {
if (isEditModal) handleSubmit(saveEdited)(); if (isEditModal) {
else setIsEditModal(!isEditModal); handleSubmit(saveTask)();
setIsEditModal(!isEditModal);
} else setIsEditModal(!isEditModal);
}} }}
> >
{isEditModal ? ( {isEditModal ? (
@@ -210,16 +231,34 @@ const ProfileTasks: FunctionComponent = () => {
</form> </form>
)} )}
{isCreating && ( {isCreating && (
<div class="flex h-full w-full flex-col items-start justify-between"> <form
class="flex h-full w-full flex-col items-start justify-between"
onSubmit={(e) => {
e.preventDefault();
handleSubmit((data) => saveTask({ ...data, id: tasks.length + 1 }))();
}}
>
<div class="flex w-full flex-row items-start justify-between"> <div class="flex w-full flex-row items-start justify-between">
<div class="me-4 flex flex-1 flex-col gap-1"> <div class="me-4 flex flex-1 flex-col gap-1">
<input class="text-2xl outline-0" maxLength={20} placeholder="Название" ref={taskNameRef} /> <input
class="text-2xl outline-0"
maxLength={20}
placeholder="Название"
{...register("name", { required: "Заполните название" })}
/>
<textarea <textarea
class="h-[5rem] w-full resize-none outline-0" class="h-[5rem] w-full resize-none outline-0"
maxLength={200}
placeholder="Описание" placeholder="Описание"
ref={taskDescriptionRef} maxLength={200}
{...register("description")}
/> />
<input
type="datetime-local"
value={calendarDate ? calendarDate.toISOString().slice(0, 16) : ""}
hidden
{...register("date")}
/>
<input type="checkbox" checked={false} hidden {...register("checked")} />
</div> </div>
<CalendarDaysIcon <CalendarDaysIcon
class="size-10 cursor-pointer" class="size-10 cursor-pointer"
@@ -230,7 +269,9 @@ const ProfileTasks: FunctionComponent = () => {
/> />
<BookmarkIcon class="ms-4 size-10 cursor-pointer" /> <BookmarkIcon class="ms-4 size-10 cursor-pointer" />
</div> </div>
<div className="mb-8 flex h-16 flex-col items-center gap-6 self-center md:mb-0 md:flex-row"> {errors.name && <p class="text-red-500">{errors.name.message}</p>}
{errors.date && <p class="text-red-500">{errors.date.message}</p>}
<div className="mb-8 flex h-16 flex-col items-center gap-6 self-center md:mb-0 md:flex-row md:self-start">
<Button <Button
className="text-sm" className="text-sm"
onClick={() => { onClick={() => {
@@ -239,36 +280,11 @@ const ProfileTasks: FunctionComponent = () => {
> >
Отмена Отмена
</Button> </Button>
<Button <Button color="red" type="submit">
color="red"
onClick={() => {
if (taskNameRef.current && taskDescriptionRef.current) {
if (!taskNameRef.current.value || !taskDescriptionRef.current.value) {
alert("Заполните все поля");
return;
}
if (!calendarDate) {
alert("Заполните дату и время");
return;
}
const task: ITask = {
id: tasks.length + 1,
name: taskNameRef.current.value,
description: taskDescriptionRef.current.value,
date: calendarDate,
checked: false,
tags: ["Математика", "Домашнее задание"],
};
setTasks([...tasks, task]);
setIsOpen(false);
setCalendarDate(null);
}
}}
>
Добавить задачу Добавить задачу
</Button> </Button>
</div> </div>
</div> </form>
)} )}
</ModalWindow> </ModalWindow>
{tasks.length > 0 ? ( {tasks.length > 0 ? (