From b0737ea6adbcbf285aab480942cb31beabd66d7e Mon Sep 17 00:00:00 2001 From: hamid zarghami Date: Thu, 9 Jul 2026 11:42:41 +0330 Subject: [PATCH] create project --- src/langs/fa.json | 1 + src/pages/taskmanager/project/Create.tsx | 150 +++++++++++++++++- .../components/CreateProjectSidebar.tsx | 82 ++++++++-- .../project/hooks/useProjectData.ts | 16 ++ .../project/service/ProjectService.ts | 7 + .../taskmanager/project/types/ProjectTypes.ts | 12 ++ 6 files changed, 245 insertions(+), 23 deletions(-) create mode 100644 src/pages/taskmanager/project/hooks/useProjectData.ts create mode 100644 src/pages/taskmanager/project/service/ProjectService.ts diff --git a/src/langs/fa.json b/src/langs/fa.json index 94f0107..7d39e6f 100644 --- a/src/langs/fa.json +++ b/src/langs/fa.json @@ -985,6 +985,7 @@ "choose_color": "انتخاب رنگ دلخواه", "users": "کاربران", "select_user": "انتخاب کاربر", + "select_workspace": "انتخاب فضای کاری", "no_users_added": "هنوز کاربری اضافه نکردی", "new_project": "افزودن پروژه", "submit_project": "ثبت پروژه", diff --git a/src/pages/taskmanager/project/Create.tsx b/src/pages/taskmanager/project/Create.tsx index 5f23b1c..c9567d8 100644 --- a/src/pages/taskmanager/project/Create.tsx +++ b/src/pages/taskmanager/project/Create.tsx @@ -1,20 +1,110 @@ +import { FC, useState } from "react"; import { TickCircle } from "iconsax-react"; +import { useFormik } from "formik"; import { useTranslation } from "react-i18next"; +import { useNavigate, useSearchParams } from "react-router-dom"; +import { toast } from "react-toastify"; +import * as Yup from "yup"; +import moment from "moment-jalaali"; import Button from "../../../components/Button"; import DatePickerComponent from "../../../components/DatePicker"; import Input from "../../../components/Input"; import Textarea from "../../../components/Textarea"; -import CreateProjectSidebar from "./components/CreateProjectSidebar"; +import { Pages } from "../../../config/Pages"; +import { ErrorType } from "../../../helpers/types"; +import { useSingleUpload } from "../../service/hooks/useServiceData"; +import CreateProjectSidebar, { + BACKGROUND_PRESETS, + SelectedUser, +} from "./components/CreateProjectSidebar"; +import { useCreateProject } from "./hooks/useProjectData"; +import { CreateProjectType } from "./types/ProjectTypes"; -const CreateProject = () => { +const CreateProject: FC = () => { const { t } = useTranslation("global"); + const navigate = useNavigate(); + const [searchParams] = useSearchParams(); + const createProject = useCreateProject(); + const singleUpload = useSingleUpload(); + + const [isActive, setIsActive] = useState(true); + const [selectedColor, setSelectedColor] = useState("#A8E6CF"); + const [selectedUsers, setSelectedUsers] = useState([]); + const [selectedBackground, setSelectedBackground] = useState(BACKGROUND_PRESETS[0]); + const [backgroundImage, setBackgroundImage] = useState(null); + const [workspaceId, setWorkspaceId] = useState(searchParams.get("workspaceId") ?? ""); + + const handleCreateProject = async (values: CreateProjectType) => { + createProject.mutate(values, { + onSuccess: () => { + toast.success(t("success")); + navigate(Pages.taskmanager.projectList); + }, + onError: (error: ErrorType) => { + toast.error(error.response?.data?.error.message[0]); + }, + }); + }; + + const formik = useFormik< + Pick + >({ + initialValues: { + name: "", + ownerName: "", + description: "", + startDate: "", + }, + validationSchema: Yup.object({ + name: Yup.string().required(t("errors.required")), + ownerName: Yup.string().required(t("errors.required")), + description: Yup.string(), + startDate: Yup.string().required(t("errors.required")), + }), + onSubmit: async (values) => { + if (!workspaceId) { + toast.error(t("taskmanager.select_workspace")); + return; + } + + let backgroundPicture = ""; + + if (backgroundImage) { + const formData = new FormData(); + formData.append("file", backgroundImage); + + try { + const uploadResult = await singleUpload.mutateAsync(formData); + backgroundPicture = uploadResult?.data?.url ?? ""; + } catch (error) { + const uploadError = error as ErrorType; + toast.error(uploadError.response?.data?.error.message[0]); + return; + } + } + + handleCreateProject({ + ...values, + startDate: moment(values.startDate, "jYYYY/jMM/jDD").format("YYYY-MM-DD"), + backgroundPicture, + backgroundColor: selectedColor, + isActive, + workspaceId, + userIds: selectedUsers.map((user) => user.id), + }); + }, + }); return (
{t("taskmanager.new_project")}
-