From c4eca9b5e6c56d20e43d40aa4e596857bb4f3ce1 Mon Sep 17 00:00:00 2001 From: Sergey Elpashev Date: Mon, 21 Apr 2025 16:01:19 +0300 Subject: [PATCH] feat: add and edit task modal --- src/components/task.tsx | 5 +- src/components/ui/Button.tsx | 13 ++- src/components/ui/Modal.tsx | 38 +++++++ src/pages/profile_tasks.dto.ts | 8 ++ src/pages/profile_tasks.tsx | 182 +++++++++++++++++++++++++++++++-- 5 files changed, 232 insertions(+), 14 deletions(-) create mode 100644 src/components/ui/Modal.tsx create mode 100644 src/pages/profile_tasks.dto.ts diff --git a/src/components/task.tsx b/src/components/task.tsx index 40a2f62..103eb76 100644 --- a/src/components/task.tsx +++ b/src/components/task.tsx @@ -5,6 +5,7 @@ import classes from "./task.module.scss"; interface TaskProps { name: string; checked?: boolean; + onClick?: () => void; } const taskStyle = tv({ @@ -27,10 +28,10 @@ const markStyle = tv({ }, }); -const Task: FunctionComponent = ({ name, checked = false }: TaskProps) => { +const Task: FunctionComponent = ({ name, checked = false, onClick = () => {} }: TaskProps) => { return ( // Временное действие для тестирования - ); diff --git a/src/components/ui/Modal.tsx b/src/components/ui/Modal.tsx new file mode 100644 index 0000000..2d7181f --- /dev/null +++ b/src/components/ui/Modal.tsx @@ -0,0 +1,38 @@ +import { cn } from "@/utils/class-merge"; +import { FunctionComponent } from "preact"; +import { Dispatch, StateUpdater, useEffect } from "preact/hooks"; + +interface ModalWindowProps { + isOpen?: boolean; + setIsOpen?: Dispatch>; + onClose?: () => void; +} +const ModalWindow: FunctionComponent = ({ isOpen, children, setIsOpen, onClose }) => { + useEffect(() => { + if (isOpen) return; + if (onClose) onClose(); + }, [isOpen]); + return ( +
{ + e.stopPropagation(); + if (setIsOpen) setIsOpen(false); + }} + class={cn( + "fixed top-0 left-0 z-50 flex h-screen w-screen cursor-pointer flex-col items-center justify-center bg-black/50", + { + hidden: !isOpen, + } + )} + > +
e.stopPropagation()} + > + {children} +
+
+ ); +}; + +export default ModalWindow; diff --git a/src/pages/profile_tasks.dto.ts b/src/pages/profile_tasks.dto.ts new file mode 100644 index 0000000..08b55de --- /dev/null +++ b/src/pages/profile_tasks.dto.ts @@ -0,0 +1,8 @@ +export interface ITask { + id: number; + name: string; + checked: boolean; + date: Date; + description: string; + tags: string[]; +} diff --git a/src/pages/profile_tasks.tsx b/src/pages/profile_tasks.tsx index 07cc1de..8643693 100644 --- a/src/pages/profile_tasks.tsx +++ b/src/pages/profile_tasks.tsx @@ -1,13 +1,49 @@ import Task from "@/components/task"; +import Button from "@/components/ui/Button"; +import ModalWindow from "@/components/ui/Modal"; import { withTitle } from "@/constructors/Component"; import { UrlsTitle } from "@/enums/urls"; import { PlusIcon } from "@heroicons/react/20/solid"; -import { FunnelIcon, MagnifyingGlassIcon } from "@heroicons/react/24/outline"; +import { + BookmarkIcon, + BookOpenIcon, + CalendarDaysIcon, + DocumentDuplicateIcon, + FunnelIcon, + MagnifyingGlassIcon, + PencilIcon, +} from "@heroicons/react/24/outline"; import { FunctionComponent } from "preact"; -import { useMemo } from "preact/hooks"; +import { useMemo, useRef, useState } from "preact/hooks"; +import { ITask } from "./profile_tasks.dto"; import classes from "./profile_tasks.module.scss"; -const example_tasks = ["Test 1", "Test 2", "Test 3", "Test 4", "Test 5", "Test 6", "Test 7", "Test 8"]; +const example_tasks: ITask[] = [ + { + checked: false, + date: new Date(), + description: "test", + id: 1, + name: "test1", + tags: ["Программирование", "Лабораторная работа"], + }, + { + checked: true, + date: new Date(2025, 6, 2), + description: "test2", + id: 3, + name: "test3", + tags: ["Информатика", "Практическая работа"], + }, + { + checked: false, + date: new Date(2025, 5, 1), + description: "test3", + id: 2, + name: "test2", + tags: ["Математика", "Домашнее задание"], + }, +]; const ProfileTasks: FunctionComponent = () => { const getDate = useMemo(() => { @@ -15,18 +51,140 @@ const ProfileTasks: FunctionComponent = () => { const formatter = new Intl.DateTimeFormat("ru-RU", { month: "long", day: "numeric" }); return formatter.format(date); }, []); + const [tasks, setTasks] = useState(example_tasks); + const [openModal, setIsOpen] = useState(false); + const [isEdit, setIsEdit] = useState(false); + const [isCreating, setIsCreating] = useState(false); + const [editContent, setEditContent] = useState(null); + const taskNameRef = useRef(null); + const taskDescriptionRef = useRef(null); return (
- {example_tasks.length > 0 ? ( + { + setIsEdit(false); + setEditContent(null); + setIsCreating(false); + }} + > + {isEdit && editContent && ( +
+
+
+

{editContent.name}

+

{editContent.description}

+
+
+ +

Редактировать

+
+
+
+
+ +

+ {Intl.DateTimeFormat("ru-RU", { + day: "2-digit", + month: "2-digit", + year: "numeric", + hour: "2-digit", + minute: "2-digit", + }).format(editContent.date)} +

+
+
+

+ + {editContent.tags[0]} +

+

+ + {editContent.tags[1]} +

+
+
+
+ )} + {isCreating && ( +
+
+
+ +