feat: creating tasks
This commit is contained in:
@@ -1,8 +1,9 @@
|
|||||||
import { IAPITag } from "@/pages/profile_tasks.dto";
|
import { IAPITag } from "@/pages/profile_tasks.dto";
|
||||||
|
import apiClient from "@/services/api";
|
||||||
import { cn } from "@/utils/class-merge";
|
import { cn } from "@/utils/class-merge";
|
||||||
import { BookOpenIcon, DocumentDuplicateIcon } from "@heroicons/react/24/outline";
|
import { BookOpenIcon, CheckIcon, DocumentDuplicateIcon, PlusCircleIcon } from "@heroicons/react/24/outline";
|
||||||
import { FunctionComponent } from "preact";
|
import { FunctionComponent } from "preact";
|
||||||
import { Dispatch, StateUpdater, useEffect, useState } from "preact/hooks";
|
import { Dispatch, StateUpdater, useEffect, useRef, useState } from "preact/hooks";
|
||||||
import Button from "./ui/Button";
|
import Button from "./ui/Button";
|
||||||
import ModalWindow, { ModalWindowProps } from "./ui/Modal";
|
import ModalWindow, { ModalWindowProps } from "./ui/Modal";
|
||||||
|
|
||||||
@@ -22,6 +23,7 @@ interface ModalTagsProps extends ModalWindowProps {
|
|||||||
first: IAPITag[];
|
first: IAPITag[];
|
||||||
second: IAPITag[];
|
second: IAPITag[];
|
||||||
};
|
};
|
||||||
|
refreshTags: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ModalTags: FunctionComponent<ModalTagsProps> = ({
|
const ModalTags: FunctionComponent<ModalTagsProps> = ({
|
||||||
@@ -31,16 +33,46 @@ const ModalTags: FunctionComponent<ModalTagsProps> = ({
|
|||||||
onChange,
|
onChange,
|
||||||
value,
|
value,
|
||||||
tagsList,
|
tagsList,
|
||||||
|
refreshTags,
|
||||||
...rest
|
...rest
|
||||||
}) => {
|
}) => {
|
||||||
const [showFirstTags, setShowFirstTags] = useState(false);
|
const [showFirstTags, setShowFirstTags] = useState(false);
|
||||||
const [showSecondTags, setShowSecondTags] = useState(false);
|
const [showSecondTags, setShowSecondTags] = useState(false);
|
||||||
|
const [showAddFirstTag, setShowAddFirstTag] = useState(false);
|
||||||
|
const [showAddSecondTag, setShowAddSecondTag] = useState(false);
|
||||||
|
const addFirstTagRef = useRef<HTMLInputElement>(null);
|
||||||
|
const addSecondTagRef = useRef<HTMLInputElement>(null);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (showFirstTags && showSecondTags) setShowFirstTags(false);
|
if (showFirstTags && showSecondTags) setShowFirstTags(false);
|
||||||
}, [showSecondTags]);
|
}, [showSecondTags]);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (showFirstTags && showSecondTags) setShowSecondTags(false);
|
if (showFirstTags && showSecondTags) setShowSecondTags(false);
|
||||||
}, [showFirstTags]);
|
}, [showFirstTags]);
|
||||||
|
|
||||||
|
const handleCreateTag = async () => {
|
||||||
|
if (!addFirstTagRef.current?.value && !addSecondTagRef.current?.value) return;
|
||||||
|
const data: { subject_name?: string; taskType_name?: string } = {};
|
||||||
|
if (addFirstTagRef.current && addFirstTagRef.current.value) data.subject_name = addFirstTagRef.current.value;
|
||||||
|
if (addSecondTagRef.current && addSecondTagRef.current.value) data.taskType_name = addSecondTagRef.current.value;
|
||||||
|
const response = await apiClient<{ success: boolean; subject?: IAPITag; taskType?: IAPITag }>(
|
||||||
|
"/api/tags/create_tags/",
|
||||||
|
{ method: "POST", body: JSON.stringify(data) }
|
||||||
|
);
|
||||||
|
if (response.success) {
|
||||||
|
refreshTags();
|
||||||
|
if (showAddFirstTag) {
|
||||||
|
const new_subject_id = response.subject!.id;
|
||||||
|
onChange!((prev) => ({ ...prev, first: new_subject_id }));
|
||||||
|
setShowAddFirstTag(false);
|
||||||
|
}
|
||||||
|
if (showAddSecondTag) {
|
||||||
|
const new_taskType_id = response.taskType!.id;
|
||||||
|
onChange!((prev) => ({ ...prev, second: new_taskType_id }));
|
||||||
|
setShowAddSecondTag(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ModalWindow
|
<ModalWindow
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
@@ -50,6 +82,8 @@ const ModalTags: FunctionComponent<ModalTagsProps> = ({
|
|||||||
onClose!();
|
onClose!();
|
||||||
setShowFirstTags(false);
|
setShowFirstTags(false);
|
||||||
setShowSecondTags(false);
|
setShowSecondTags(false);
|
||||||
|
setShowAddFirstTag(false);
|
||||||
|
setShowAddSecondTag(false);
|
||||||
}}
|
}}
|
||||||
className="relative h-[14rem] justify-between py-4 md:h-[14rem] md:w-[25rem]"
|
className="relative h-[14rem] justify-between py-4 md:h-[14rem] md:w-[25rem]"
|
||||||
zIndex={70}
|
zIndex={70}
|
||||||
@@ -58,21 +92,31 @@ const ModalTags: FunctionComponent<ModalTagsProps> = ({
|
|||||||
<div class="flex w-[85%] flex-col gap-2 md:w-full">
|
<div class="flex w-[85%] flex-col gap-2 md:w-full">
|
||||||
<Button
|
<Button
|
||||||
className="flex w-full flex-row items-center justify-center gap-1 text-[1rem]!"
|
className="flex w-full flex-row items-center justify-center gap-1 text-[1rem]!"
|
||||||
onClick={() => setShowFirstTags(!showFirstTags)}
|
onClick={() => {
|
||||||
|
setShowFirstTags(!showFirstTags);
|
||||||
|
setShowSecondTags(false);
|
||||||
|
setShowAddFirstTag(false);
|
||||||
|
setShowAddSecondTag(false);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<BookOpenIcon class="size-6" />
|
<BookOpenIcon class="size-6" />
|
||||||
{tagsList?.first?.find((tag) => tag.id === value?.first)?.name || "Предмет"}
|
{tagsList?.first?.find((tag) => tag.id === value?.first)?.name || "Предмет"}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
className="flex w-full flex-row items-center justify-center gap-1 text-[1rem]! break-words"
|
className="flex w-full flex-row items-center justify-center gap-1 text-[1rem]! break-words"
|
||||||
onClick={() => setShowSecondTags(!showSecondTags)}
|
onClick={() => {
|
||||||
|
setShowSecondTags(!showSecondTags);
|
||||||
|
setShowFirstTags(false);
|
||||||
|
setShowAddFirstTag(false);
|
||||||
|
setShowAddSecondTag(false);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<DocumentDuplicateIcon class="size-6" />
|
<DocumentDuplicateIcon class="size-6" />
|
||||||
{tagsList?.second?.find((tag) => tag.id === value?.second)?.name || "Тема"}
|
{tagsList?.second?.find((tag) => tag.id === value?.second)?.name || "Тема"}
|
||||||
</Button>
|
</Button>
|
||||||
{showFirstTags && (
|
{showFirstTags && (
|
||||||
<div class="absolute top-full left-0 mt-3 ml-2 flex h-fit w-[18rem] flex-col items-center rounded-[4rem] bg-white px-8 py-4 text-xs md:top-0 md:left-full md:mt-0 md:ml-5">
|
<div class="absolute top-full left-0 mt-3 ml-2 flex h-fit w-[18rem] flex-col items-center gap-3 md:top-0 md:left-full md:mt-0 md:ml-5">
|
||||||
<div class="flex h-fit max-h-[45vh] w-full flex-col gap-3 overflow-y-auto">
|
<div class="flex h-fit max-h-[45vh] w-full flex-col gap-3 overflow-y-auto rounded-[4rem] bg-white px-8 py-4 text-xs">
|
||||||
{tagsList?.first.map((tag) => (
|
{tagsList?.first.map((tag) => (
|
||||||
<div
|
<div
|
||||||
class="flex cursor-pointer flex-row gap-2"
|
class="flex cursor-pointer flex-row gap-2"
|
||||||
@@ -95,12 +139,28 @@ const ModalTags: FunctionComponent<ModalTagsProps> = ({
|
|||||||
<p>{tag.name}</p>
|
<p>{tag.name}</p>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
<button
|
||||||
|
class="mt-2 flex w-full cursor-pointer flex-row items-center gap-2"
|
||||||
|
onClick={() => {
|
||||||
|
setShowAddFirstTag(!showAddFirstTag);
|
||||||
|
setTimeout(() => addFirstTagRef.current?.focus(), 100);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<PlusCircleIcon class="size-5" />
|
||||||
|
<span>Добавить</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
{showAddFirstTag && (
|
||||||
|
<div class="flex w-full flex-row items-center rounded-[4rem] bg-white px-8 py-4 text-xs">
|
||||||
|
<input placeholder="Введите текст" class="flex-1 outline-0" ref={addFirstTagRef} />
|
||||||
|
<CheckIcon class="size-6 cursor-pointer" onClick={handleCreateTag} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{showSecondTags && (
|
{showSecondTags && (
|
||||||
<div class="absolute top-full left-0 mt-3 ml-2 flex h-fit w-[18rem] flex-col items-center rounded-[4rem] bg-white px-8 py-4 text-xs md:top-0 md:left-full md:mt-0 md:ml-5">
|
<div class="absolute top-full left-0 mt-3 ml-2 flex h-fit w-[18rem] flex-col items-center gap-3 md:top-0 md:left-full md:mt-0 md:ml-5">
|
||||||
<div class="flex h-fit max-h-[45vh] w-full flex-col gap-3 overflow-y-auto">
|
<div class="flex h-fit max-h-[45vh] w-full flex-col gap-3 overflow-y-auto rounded-[4rem] bg-white px-8 py-4 text-xs">
|
||||||
{tagsList?.second.map((tag) => (
|
{tagsList?.second.map((tag) => (
|
||||||
<div
|
<div
|
||||||
class="flex cursor-pointer flex-row gap-2"
|
class="flex cursor-pointer flex-row gap-2"
|
||||||
@@ -123,7 +183,23 @@ const ModalTags: FunctionComponent<ModalTagsProps> = ({
|
|||||||
<p>{tag.name}</p>
|
<p>{tag.name}</p>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
<button
|
||||||
|
class="mt-2 flex w-full cursor-pointer flex-row items-center gap-2"
|
||||||
|
onClick={() => {
|
||||||
|
setShowAddSecondTag(!showAddSecondTag);
|
||||||
|
setTimeout(() => addSecondTagRef.current?.focus(), 100);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<PlusCircleIcon class="size-5" />
|
||||||
|
<span>Добавить</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
{showAddSecondTag && (
|
||||||
|
<div class="flex w-full flex-row items-center rounded-[4rem] bg-white px-8 py-4 text-xs">
|
||||||
|
<input placeholder="Введите текст" class="flex-1 outline-0" ref={addSecondTagRef} />
|
||||||
|
<CheckIcon class="size-6 cursor-pointer" onClick={handleCreateTag} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -378,6 +378,7 @@ const ProfileCalendar: FunctionComponent = () => {
|
|||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<ModalTags
|
<ModalTags
|
||||||
|
refreshTags={fetchTags}
|
||||||
isOpen={openModalTags}
|
isOpen={openModalTags}
|
||||||
setIsOpen={setOpenModalTags}
|
setIsOpen={setOpenModalTags}
|
||||||
tagsList={example_tags}
|
tagsList={example_tags}
|
||||||
|
|||||||
@@ -395,6 +395,7 @@ const ProfileTasks: FunctionComponent = () => {
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<ModalTags
|
<ModalTags
|
||||||
|
refreshTags={fetchTags}
|
||||||
zIndex={70}
|
zIndex={70}
|
||||||
isOpen={openModalTags}
|
isOpen={openModalTags}
|
||||||
setIsOpen={setOpenModalTags}
|
setIsOpen={setOpenModalTags}
|
||||||
|
|||||||
Reference in New Issue
Block a user